Smarter routing with nested resources

I have a number of resources that I want to access in various scopes. The index action would change slightly depending on its scope, but the rest of the actions would be identical aside from needing to preserve the url scope in links and redirects.

For example:

map.resources :categories do |categories|   categories.resources :products do |products|     products.resources :components   end end

map.resources :products do |products|   products.resources :components end

map.resources :components

This enables the following routes all to work:

/categories/1/products/1/components/1 /products/1/components/1 /components/1

However, if I understand correctly, I have to specify which route in the named routes:

category_product_components_path product_components_path components_path

I'd like to be able to use components_path and have it be smart enough based on the options and params to preserve as much scoped routing as possible. For example:

Calling components_path in /categories/1/products/1 -> /categories/1/products/1/components Calling components_path in /products/1 -> /products/1/components Calling components_path somewhere else -> /components

Is there any way to do this?

category_product_components_path is the only way afaik, without hacking up your own version of it.

Why would you need to have 3-level deep nested routes anyway? “/categories/1/products/1/components/1/” Really all you’re looking at here is the component, who cares what category and product it’s from, you can do that query in the controller.

Ryan Bigg wrote:

category_product_components_path is the only way afaik, without hacking up your own version of it.

Why would you need to have 3-level deep nested routes anyway? “/categories/1/products/1/components/1/” Really all you’re looking at here is the component, who cares what category and product it’s from, you can do that query in the controller.

For the components index page I need to know if I should display all components or only those that belong to the given product. For the actions like show, edit and update I need to preserve that state so when I go back to the index I go back to the right index page. The user will start on an index page at some level of scoping, he then goes to show a component. At this point I have the referer so I don’t have a problem going back yet. Then if he goes from show to edit and update that component. At this point if I’m only at “/components/1” I have no way of knowing what index page I should go back to.

In my production system I have many resources that have many relations (one model has ~30 associations). So there are are many places where I need an index of all records that belong to another, to be able to do multiple actions to an individual record, and finally go back to the original index page.

I have used the session to to store where I should go back to, but that has its own nasty set of problems. It seems that this state should be kept in the URL.

Ok, well /products/1/components/1 will let you go back as far as you need to go back, right?

Ryan Bigg wrote:

Ok, well /products/1/components/1 will let you go back as far as you need to go back, right? Correct, assuming I came through /categories/products/1. The problem is I may have just come through /products/1. I basically just need to keep whatever the prefix is before the /components. I have hacked together some custom url helpers in which I list all the possible entrance paths and the params that trigger that path. It more or less works, but in theory all the information I’m duplicating in those helpers exists in the routes somewhere. Maybe I should look into reflecting on routes.