Rails 3 - Nested resources and polymorphic paths: OK to two levels, but break at three

Don Leatham picture Don Leatham · May 7, 2011 · Viewed 8.6k times · Source

I'm trying to do a simple family reunion site with: "posts", "families", "kids", and "pictures". Ideally I'd like the routes/relationships to be structured this way:

  resources :posts do
    resources :pictures
  end

  resources :fams do
     resources :pictures
     resources :kids do
       resources :pictures
     end
  end

In the models I have the necessary "belongs_to" and "has_many" relationships set between fams and kids. Fams, kids, and posts all are defined with "has_many :pictures, :as => :imageable" while pictures are defined as: belongs_to :imageable, :polymorphic => true

When trying to do link_to "Edit" and link_to "Destroy" in the pictures views I run into all sorts of _path problems. polymoric_path works fine at two levels, namely for posts-pictures and fams-pictures but it fails to handle the three level case of fams-kids-pictures. I'm guessing that it was not designed to handle the two levels of "imageable" objects above the picture object. Another issue is that in one instance the pictures controller has to handle a "one level" resource-nesting situation and in another it has to handle a "two levels" situation. Not sure how to approach this.

One thing I did try was to not nest resources more than one deep, per the Ruby Guides directions. I structured them like this:

  resources :posts do
    resources :pictures
  end

  resources :fams do
     resources :pictures
     resources :kids
  end

  resources :kids do
     resources :pictures
  end

This caused another set of problems with paths since the fam to kid relationship was no longer preserved. I also could not get polymorphic_path to function correctly accross all the different picture views.

So here is my main question: Does anyone know of a Rails 3 example/tutorial where nested resources, belongs-to/has_many, and polymorphic relationships are all put together, especially where it is not just the simple, two-level relationship that most examples show? (I'm fairly new to Rails and the Rails 2 examples I've found in these areas are confusing given my lack of Rails historical experience.)

Or can someone tell me how to structure the link_to EDIT and link_to DELETE statements for my picture views, as well as the redirect-to statement for my create, update, and destroy methods in my pictures controller?

Thanks!

Answer

mikong picture mikong · Jul 21, 2011

Your code example that limited your nesting to 2 levels is quite near the answer. To avoid duplicate routes for fams->kids and kids, you can use the :only option with a blank array so that the 1st-level kids will not generate routes except in the context of kids->pictures, like so:

resources :posts do
  resources :pictures
end

resources :fams do
  resources :pictures
  resources :kids
end

resources :kids, only: [] do # this will not generate kids routes
   resources :pictures
end

For the above code, you can use the following to construct your polymorphic edit url:

polymorphic_url([fam, picture], action: :edit) # using Ruby 1.9 hash syntax
polymorphic_url([kid, picture], action: :edit)