I have two types of products that are nested under the same categories. The routes I have setup are
resources :categories, path: '/', only: [:show] do
resources :subcategories, path: '/', only: [:show] do
resources :amazon_products, path: '/', only: [:show]
resources :other_products, path: '/', only: [:show]
end
end
which I was previously accessing using this link
<%= link_to "View Product Page", [product.collection, product.category, product.subcategory, product], class: 'product__link' %>
which that resulted in something like this url after friendly_id
finished with it
/cleansers/face-wash-and-cleansers/blemish-remedy-acne-treatment-gelee-cleanser
The issue is that the link only resolves for amazon_products and I'm not sure how to make it differentiate between the two. I think the problem is in the way I am referencing the path since when I enter rails routes in the console, I can see the two different paths there like so
category_subcategory_amazon_product
GET :category_id/:subcategory_id/:id(.:format)
amazon_products#show
category_subcategory_other_product
GET /:collection_id/:category_id/:subcategory_id/:id(.:format)
other_products#show
I tried specifically referencing the other product path using the link
category_subcategory_other_product_path(product.category, product.subcategory, product)
but it is giving me an ActiveRecord::RecordNotFound since its still looking in the wrong controller
app/controllers/amazon_products_controller.rb:5:in `show'
How do I tell rails to differentiate between these two resources?
When you boil it down, Rails routes are relatively simple patterns that match URIs and dispatch requests to the proper controller/method.
If you had specified your nested routes in their basic form:
resources :categories, only: [:show] do
resources :subcategories, only: [:show] do
resources :amazon_products, only: [:show]
resources :other_products, only: [:show]
end
end
The resulting URI patterns for the product level would look like:
/categories/<id>/subcategories/<id>/amazon_products/<id>
/categories/<id>/subcategories/<id>/other_products/<id>
Admittedly verbose, but obviously distinct, patterns.
The issue is that you are using path: '/'
on the resources to remove everything unique about the resource routes. So, your product-level route patterns are:
category_subcategory_amazon_product: /<id>/<id>/<id>
category_subcategory_other_product: /<id>/<id>/<id>
Since the two patterns are identical, Rails falls back to the time honoured practice of matching the first one defined. You can demonstrate that for yourself by swapping :other_products
so it is first; its controller will then be the one always invoked.
NB: It doesn't matter that you are using friendly-id -- that just changes what the IDs look like to the user, not the basic route pattern.
The solution is to simply reintroduce some uniqueness, at least at the product level.
resources :categories, path: '/', only: [:show] do
resources :subcategories, path: '/', only: [:show] do
resources :amazon_products, path: 'amazon', only: [:show]
resources :other_products, path: 'other', only: [:show]
end
end
The result will be route patterns that Rails can actually distinguish:
category_subcategory_amazon_product: /<id>/<id>/amazon/<id>
category_subcategory_other_product: /<id>/<id>/other/<id>