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.