Предположим, у меня такая полиморфная структура.
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. Зачем отбрасывать эту информацию?
Итак: как это можно сделать?