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!
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)
Have been having this exact same problem for a while. I have it working now, but it isn't beautiful :S
From a nested monster like:
http://localhost:3000/destinations/3/accommodations/3/accommodation_facilities/52
Your params object ends up looking like this:
action: show
id: "52"
destination_id: "3"
accommodation_id: "3"
controller: accommodation_facilities
where "id" represents the current model id (last on the chain) and the other ones have model_name_id
To correctly render another nested link on this page, you need to pass in an array of objects that make up the full path, eg to link to a fictional FacilityType object you'd have to do:
<%= link_to "New", new_polymorphic_path([@destination, @accommodation, @accommodation_facility, :accommodation_facility_type]) %>
To generate this array from the params object, I use this code in application_helper.rb
def find_parent_models(current_model = nil)
parents = Array.new
params.each do |name, value|
if name =~ /(.+)_id$/
parents.push $1.classify.constantize.find(value)
end
end
parents.push current_model
parents
end
Then to automatically make the same link, you can merrily do:
<%= link_to "New", new_polymorphic_path(find_parent_models(@accommodation_facility).push(:accommodation_facility_type)) %>
Any pointers on making this solution less sketchy are very welcome :]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With