Предположим, что у меня есть полиморфная структура как это.
map.resources :bar, :has_many => :foo
map.resources :baz, :has_many => :foo
map.resources :qux, :has_many => :foo
class Foo
belongs_to :parent, :polymorphic => true
end
class FooController < AC
before_filter :find_parent
...
private
def find_parent
# ugly way:
@parent = if params[:bar_id]
Bar.find(params[:bar_id])
elsif params[:baz_id]
Baz.find(params[:baz_id])
elsif params[:qux_id]
Qux.find(params[:qux_id])
end
end
end
Это довольно ужасно. Каждый раз, когда мы добавляем новую вещь, которой это могло бы принадлежать, мы должны добавить его несухо к этому before_filter.
Это ухудшается, также. Предположим, что Foos являются действительно полиморфными вещами, которые могли обнаружиться где угодно, как комментарии или теги. И предположите, что у Вас есть следующие маршруты:
map.resources :bar, :has_many => :foo do |bar|
bar.resources :baz, :has_many => :foo
end
map.resources :qux, :has_many => :foo do |qux|
qux.resources :baz, :has_many => :foo
end
... теперь мы должны волноваться о том, проверить ли на bar_id или baz_id сначала.
Для более сложных ресурсов возможно, что этого даже не будет достаточно, чтобы быть уверенным, что Вы получаете идентификатор родителя.
То, что было бы идеально, - то, если мы могли бы сделать что-то вроде этого:
def get_parent
# fetch the parameter that immediately preceeded :id
@parent = if x = params.before(:id)
# polymorphic find
x.key.to_s[0..-4].classify.constantize.find x.value
end
end
В конце концов, наши маршруты уже кодируют родителя на основании порядка параметров в URL. Почему отбрасывание та информация?
Так: как это может быть сделано?
Вы должны иметь возможность запросить Foo.parent
, вам нужно будет что-то Как это:
class Bar < ActiveRecord::Base
has_many :foos, :as => :parent
...
end