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
  end
  
  collection do
    get :long
  end
end    

Here’s how it looks currently in Rails 2:

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

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 have catalog#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
  end
end    

Or you can also write the same action this way:

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

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
end

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
end

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 :).


Rizwan Reza

Hello,
Urging to bring the best of design & development in their application on the web, I am a software craftsman & I make web applications.

Spots of Interest

Currently Reading