Suppose I have a polymorphic structure like this.
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
That's pretty ugly. Whenever we add a new thing that it might belong to, we need to add it un-DRYly to that before_filter.
It gets worse, too. Suppose that Foos are really polymorphic things that could show up anywhere, like comments or tags. And suppose that you have the following routes:
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
... now we have to worry about whether to check for bar_id or baz_id first.
For more complex resources, it's possible that this won't even be enough to be sure you get the parent's id.
What would be ideal is if we could do something like this:
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
After all, our routes already encode the parent by virtue of the order of parameters in the URL. Why discard that information?
So: how can this be done?