Revamped Routes in Rails 3

While much of Rails 3 is seeing an internal rewrite, the Routes DSL has seen a complete revision in Rails 3. It has been rewritten from the ground up a few times before, and it has brought speed and flexibility with each iteration. This time, it’s no exception as the DSL feels more at home to a typical Rubyist.

The new DSL takes less keystrokes and looks clean. Here’s a typical RESTful route file in Rails 3:

resources :products do
resource :category

member do
post :short

collection do
get :long

Here’s how it looks currently in Rails 2:

map.resources :products, :member => {:short => :post}, :collection => {:long => :get} do |products|
products.resource :category

As you can see, the example from Rails 3 is much cleaner and more Rubyish. Let’s take a quick overview on how you’d define different types of routes in Rails 3.

Default Route

The default route in Rails 3, match '/:controller(/:action(/:id))', is much more explicit as the parenthesis denote optional parameters.

Regular Routes

match 'products/:id' => 'catalog#view'

Rather than defining different keys for controller and action, you just havecatalog#view, which is awesome. This does the same as this:

map.connect 'products/:id', :controller => 'catalog', :action => 'view' 

Named Routes

The distinction between regular routes and named routes is harder as compared to Rails 2. The only difference between them is that the regular route above has a parameter in the first argument.

match 'logout', :to => 'sessions#destroy'

Much cleaner than what we’ve done in Rails 2:

map.logout '/logout', :controller => 'sessions', :action => 'destroy'

Empty Route

The root of the web site is routed to the empty route. Rails 2 added a nice shortcut to this, map.root :controller => "welcome", :action => 'show', which is now simply root :to => 'welcome#show'.

RESTful Routes

These are the default and the preferred way of doing development since Rails 2. Taking notice of that, they have seen some nice enhancements along the way. A typical RESTful route has become simpler:

resources :products

This would generate all the neat helpers we have come to love and they also route the URLs accordingly. Just like before, you can add multiple resources in a single line.

More RESTful Actions

We can add RESTful actions to this resource in a couple of ways:

resources :products do
collection do
get :sold
post :on_offer

Or you can also write the same action this way:

resources :products do
get :sold, :on => :collection

You must have noted that the first of these is good if you have more than one action. You can also write member routes in the same way.

Nested Resources

In Rails 2, nested resources were defined by a block or using :has_many or :has_one key. Both of these have been superseded by a block:

resources :projects do
resources :tasks, :people

Namespaced Resources

These are especially useful when defining resources in a folder and it can’t get any cleaner than this:

namespace :admin do
resources :projects

I’ve tested these with the latest Rails source code and from the looks of it, I think the Rails core has frozen the Routes DSL feature-wise. If you want to test them yourself, I recommend checking out Fabio Akita’s third_rails. There is a helpful documentation in the routes file as well.

Routes in Rails 3 have been revamped for a good reason. You’d be giving less time to Routes file in Rails now. Not to mention, the ‘.rb’ part of the file feels like it again :).

Originally posted on December 20, 2009.