Implicit routing to nested collections

I've recently filed an enhancement request to allow drawing nested
route urls that are more user and search engine friendly. The ticket
is here:
http://rails.lighthouseapp.com/projects/8994/tickets/436-implied-routes-to-nested-collections

I'm seeking feedback. There's a plugin to enable easy experimentation,
and a patch to rails, both hosted on github and linked from the
ticket.

This patch really works best when using "pretty urls" and results in a
url like so:
/local/categories/restaurants/subcategories/korean/states/california/
cities/mountain-view/businesses/totoro-tofu-house

to become:
/local/restaurants/korean/california/mountain-view/totoro-tofu-house

By changing your routes from this:
map.namespace :local do |local|
  local.resources :categories do |categories|
    categories.resources :subcategories do |subcategories|
      subcategories.resources :states do |states|
        states.resources :cities do |cities|
          cities.resources :businesses
        end
      end
    end
  end
end

to this:
map.namespace :local do |local|
  local.resources :categories, :default => true, :show
=> :subcategories do |categories|
    categories.resources :subcategories, :show => :states do |
subcategories>
      subcategories.resources :states, :show => :cities do |states|
        states.resources :cities, :show => :businesses do |cities|
          cities.resources :businesses
        end
      end
    end
  end
end

Clearly this approach results in a routing collision of the show
action and the index action and you can control which one will get
precedence in the routing table by using :show or :default. In all
cases, both routes gets written so that the named routes work as
expected, even though they both are recognized as the same.

Thanks,
Chris

I think this would be extremely useful. I created a fairly hackish
monkey patch to Rails to use in a few projects that supports a new
method called "root_resources" which would basically just eliminate that
corresponding path segment. However it looks like your method is much
more clean and I'll start to use your plugin immediately, but would like
to see this in Rails core.

In general I feel there are some flexibility issues with the current
Rails resource routing system that I find myself hacking around when
implementing any sufficiently complex application, and this addition
would go a long way towards eliminating them.

Aside from nested resources such as in your example, this might also be
useful in many other situations, such as allowing the root of a project
to directly represent a resource not unlike how twitter works with URLs
like http://twitter.com/rubiety. Using this plugin you could define (at
the bottom of the routes file!):

map.resources :users, :default => true do
  ...
end

And have users_url('rubiety') directly generate
http://twitter.com/rubiety rather than force it to be something like
http://twitter.com/users/rubiety.

+1

I'm glad you got the point of :default, that's why I chose that name.

You can also use :default to merge several resources into the same
namespace and use routing requirements to distinguish the correct
controller based on the fine structure of the identifiers, e.g. a zip
code is 5 digits and a city is not, so assuming your controllers are
read only (e.g. you're using admin controllers for creation of data)
you can lump both zip codes and cities under states without any need
for an extra scope.

I know it may not seem like a big deal, but when you're building an
search engine optimized website, these are the types of small things
that can make the difference between being on the first page of
results and the second.

-chris

Great plugin! I plan on using this and I am hoping you could
elaborate on how to use :default to merge resources into the same
namespace?

You can also use :default to merge several resources into the same
namespace and use routing requirements to distinguish the correct
controller based on the fine structure of the identifiers

I have a routing issue similar to your example, only my routes are
formatted in this order state, city, category, subcategory,
businesses. And I would like to add an addition mapping for state,
city, keword, businesses. Is there a way to do this with your plugin?

Thank for you help,

Kevin Beck

Hi Kevin,

Glad you like it!

elaborate on how to use :default to merge resources into the same namespace?

  map.namespace :merged do |merged|
    merged.root :controller => "merged", :action => "index"
    merged.resources :zipcodes, :default => true, :requirements =>
{:id => /\d{5}/}
    merged.resources :states, :default => true
  end

Is there a way to do this with your plugin?

Probably. But I'm not sure what urls you want and what you've tried so
far that didn't work. Go ahead and reply directly to me with more
details and I'll help you out.

-Chris