I have nested resources as below:
resources :categories do
resources :products
end
According to the Rails Guides,
You can also use url_for with a set of objects, and Rails will automatically determine which route you want:
<%= link_to 'Ad details', url_for([@magazine, @ad]) %>
In this case, Rails will see that @magazine is a Magazine and @ad is an Ad and will therefore use the magazine_ad_path helper. In helpers like link_to, you can specify just the object in place of the full url_for call:
<%= link_to 'Ad details', [@magazine, @ad] %>
For other actions, you just need to insert the action name as the first element of the array:
<%= link_to 'Edit Ad', [:edit, @magazine, @ad] %>
In my case, I have the following code which was fully functional:
<% @products.each do |product| %>
<tr>
<td><%= product.name %></td>
<td><%= link_to 'Show', category_product_path(product, category_id: product.category_id) %></td>
<td><%= link_to 'Edit', edit_category_product_path(product, category_id: product.category_id) %></td>
<td><%= link_to 'Destroy', category_product_path(product, category_id: product.category_id), method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
Obviously it is a little too verbose and I wanted to shorten it using the trick mentioned above from rails guides.
But if I changed the Show and Edit link as follows:
<% @products.each do |product| %>
<tr>
<td><%= product.name %></td>
<td><%= link_to 'Show', [product, product.category_id] %></td>
<td><%= link_to 'Edit', [:edit, product, product.category_id] %></td>
<td><%= link_to 'Destroy', category_product_path(product, category_id: product.category_id), method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
Neither of them works any more, and the pages complains the same thing:
NoMethodError in Products#index
Showing /root/Projects/foo/app/views/products/index.html.erb where line #16 raised:
undefined method `persisted?' for 3:Fixnum
What did I miss?
In a nested route, the belongs_to (child) association is always nested under the has_many (parent) association. The first step is to add the nested routes like so: In the above Rails router example, the 'index' and 'show' routes are the only nested routes listed (additional or other resources can be added).
Difference between singular resource and resources in Rails routes. So far, we have been using resources to declare a resource. Rails also lets us declare a singular version of it using resource. Rails recommends us to use singular resource when we do not have an identifier.
Running route helpers in the rails console is a great way of testing out routes to see what their exact output will be. Column 4 - This column shows the controller and action with a syntax of controller#action.
The way Rails is 'automagically' knowing which path to use is by inspecting the objects you pass for their classes, and then looking for a controller whose name matches. So you need to make sure that what you are passing to the link_to
helper is the actual model object, and not something like category_id
which is just a fixnum
and therefore has no associated controller.
<% @products.each do |product| %>
<tr>
<td><%= product.name %></td>
<td><%= link_to 'Show', [product.category, product] %></td>
<td><%= link_to 'Edit', [:edit, product.category, product] %></td>
<td><%= link_to 'Destroy', [product.category, product], method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
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