Ruby on Rails 2.1 - Routes System



Rails parses the URL to determine the controller, action, and parameters for the request. With Rails routing, parts of the URL can specify additional parameters, and the entire routing process is under your control. Routing rules work the same on any web server.

The config/routes.rb file is at the heart of the Rails routing system. This file contains rules that try to match the URL path of a request and determine where to direct that request. The rules are tested in the order they are defined in the file. The first rule to match a request's URL path determines the fate of that request.

The routing system actually does two things −

  • It maps requests to action methods inside the controllers.

  • It writes URLs for you for use as arguments to methods like link_to, redirect_to, and form_tag.

Thus, the routing system knows how to turn a visitor's request URL into a controller/action sequence. It also knows how to manufacture URL strings based on your specifications.

Consider the following route installed by Rails when you generate your application −

map.connect ':controller/:action/:id'

This route states that it expects requests to consist of a :controller followed by an :action that in turn is fed some :id.

If you get an incoming request for "http://localhost:3000/book/edit/2", then it will map as follows −

params = {  :controller => 'book',
   :action     => 'edit',
   :id         => '2'
}

Thus the default routing (if you don't modify the routing rules) is −

http://<base-url>/<controller>/<action>/<id>

A URL like http://www.example.com/book/update/20 calls the update method (the action) in the BooksController class (the controller) with an id parameter set to the value 20.

The following code block will set up book as the default controller if no other is specified. It means visiting '/' would invoke the book controller.

ActionController::Routing:Routes.draw do |map|
   map.connect ':controller/:action/:id',:controller => 'book'
end

You can also define a default action if no action is specified in the given URL −

ActionController::Routing:Routes.draw do |map|
   map.connect ':controller/:action/:id', 
   :action => 'edit',:controller => 'book'
end

Now, you can all edit methods inside the book controller to edit book with ID as 20 as follows −

http://localhost:3000/2

Route Priority

Routes have priority defined by the order of appearance of the routes in the routes.rb file. The priority goes from top to bottom.

The last route in that file is at the lowest priority and will be applied last. If no route matches, 404 is returned.

Modifying the Default Route

You can change the default route as per your requirement. In the following example, we are going to interchange controller and action as follows −

# Install the default route as the lowest priority.
map.connect ':action/:controller/:id'

Now, to call action from the given controller, you would have to write your URL as follows −

http://localhost:3000/action/controller/id

It's not particularly logical to put action and controller in such sequence. The original default (the default default) route is better and recommended.

The Ante-Default Route

The 'ante-default' route looks as follows −

map.connect ':controller/:action/:id.:format'

The .:format at the end matches a literal dot and a wildcard "format" value after the id field. That means it will match, for example, a URL like this −

http://localhost:3000/book/show/3.xml

Here, inside the controller action, your params[:format] will be set to xml.

The Empty Route

The empty route is sort of the opposite of the default route. In a newly generated routes.rb file, the empty route is commented out, because there's no universal or reasonable default for it. You need to decide what this nothing URL should do for each application you write.

Here are some examples of fairly common empty route rules −

map.connect '', :controller => "main", :action => "welcome"
map.connect '', :controller => "main"

Here is the explanation of the above rules −

  • The first one will search for welcome action inside main controller even if you type just http://localhost:3000.

  • That last one will connect to http://localhost:3000/main/index. Here index is the default action when there's none specified.

Rails 2.0 introduces a mapper method named root which becomes the proper way to define the empty route for a Rails application, like this −

map.root :controller => "homepage"

Defining the empty route gives people something to look at when they connect to your site with nothing but the domain name.

Named Routes

As you continue developing your application, you will probably have a few links that you use throughout your application. For example, you will probably often be putting a link back to the main listings page. Instead of having to add the following line throughout your application, you can instead create a named route that enables you to link to a shorthand version of that link −

link_to 'Home', :controller => 'classified', :action => 'list'

You can define named routes as follows. Here instead of using connect, you are using a unique name that you can define. In this case, the route is called home. The rest of the route looks similar to the others you have created.

map.home '', :controller => 'classified', :action => 'list'

Now, you can use this in the controllers or views as follows −

<%= link_to 'Back', home_url %>

Here, instead of listing the :controller and :action to which you will be linking, you are instead putting the name of the route followed by _url. Your user shouldn't notice any difference. Named routing is merely a convenience for the Rails developer to save some typing. The above case can be written without the named route as follows −

<%= link_to 'Back', {:action => 'list'} %>

Pretty URLs

Routes can generate pretty URLs. For example −

map.connect 'articles/:year/:month/:day',
   :controller => 'articles',
   :action     => 'find_by_date',
   :year       => /\d{4}/,
   :month      => /\d{1,2}/,
   :day        => /\d{1,2}/

# Using the route above, the url below maps to:
# params = {:year => '2005', :month => '11', :day => '06'}
# http://localhost:3000/articles/2005/11/06

To obtain more detail on Routes, please go through ActionController::Routing.

Advertisements