Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails - Succinctly finding the parent resource of a polymorphically nested resource

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?

like image 738
Sai Avatar asked Oct 15 '22 10:10

Sai


1 Answers

You should be able to ask for foo.parent

You'll need to have something like this:

class Bar < ActiveRecord::Base
  has_many :foos, :as => :parent
  ...
end
like image 184
Mark Swardstrom Avatar answered Oct 21 '22 05:10

Mark Swardstrom