Courtesy of Twitter

Routing Introduction

Now that we have our models, we can now define our routing. Routing defines what URLs do what in your application and all of the configuration is kept in one place: config/routes.rb.

This file will already have 2 lines in it already, along with around 30 commented out lines followed by two uncommented lines. The first two lines after ActionController::Routing::Routes.draw do |map| will look like:

First two lines

map.resources :users
map.resource :session

These two lines are defining the routes and methods for the users and session controller and was written into our routes.rb from our restful_authentication generator. The map.resource :session is flawed, as it’s generated a SessionController but by default map.resource :session goes to SessionsController, but restful authentication generated SessionController (app/controllers/session_controller.rb) instead. To fix this, we’ll suffix map.resource :session with the option of :controller => “session” so that it looks like map.resource :session, :controller => “session”.

The next thirty lines are examples of how to use the routes file covering:

  • Regular routing
  • Named routing
  • Resource routing
  • Resource routing with options
  • Resource routing with sub resources
  • Resource routing within namespaces

You can delete these lines if you like.

The final two lines define the final routes for our application. These are the last resort routes and generally will not be called in our application, but we’ll leave them there for now, as they may come in handy later on.

We’re going to define some named routes in order to give us prettier URLs for when the user wants to login, signup or logout.

New lines in our routes.rb file, somewhere near the top.

map.connect ‘login’, :controller => “session”, :action => “new”
map.connect ’signup’, :controller => “users”, :action => “new”
map.connect ‘logout’, :controller => “session”, :action => “destroy”

We’re able to pass in methods on the map object that don’t exist thanks to the magic of method_missing. method_missing is the last method to get called in the method chain when all else fails and this can be overwritten, as it has been in this case. These three lines will map /login, /signup and /logout to their respective controllers and actions specified after the method call.

We’re going to now define our resource routing. The way we do this is we call map.resources and then pass in what we want to make a resource:

Underneath map.logout … in config/routes.rb

map.resources :forums

This will give us access to using methods to generate URLs such as /forums to go to our index action in our forums (forums_path) controller, /forums/1 to go to the show action (forum_path([id or forum object]) and /forums/1/edit to go to edit action (edit_forum_path([id or forum object]).

This is all well and good, but we don’t have our edit action located at /forums/1/edit, we’ve put it into a namespaced controller so we should also have a namespaced route to point to the correct location. To do this we call map.namespace(:admin) before calling #resources, like this:

config/routes.rb

map.namespace(:admin) do |admin|
admin.resources :forums
end

What this has done is made routes exactly like the above, but it’s prefixed them with /admin/ so that we can now go to our namespaced controllers rather than their non-namespaced counterparts.

Now to set up a default route ,often referred to as root, for people navigating to our domain we have to use a method called #root on the map object, like this:

config/routes.rb

map.root :controller => “forums”, :action => “index”

I feel this is better placed at the very top of our routes file, because of how the routes file is processed. Rails will go through each entry in the routes file until it finds one that matches what the URL is, and then it will act on that. If our root route is at the top then it will be matched first reducing the time it takes for the application to process the home page, but only by a few milliseconds.

If you start your server now by opening a console window and typing mongrel_rails start in the application’s root directory (also referred to as RAILS_ROOT). This will start a single Mongrel server in development mode which will serve our application for as long as it’s running. Development mode means it will reload all the code in the app/ folder every time a request comes in, as compared to production in which it will load it only once. Opening your browser, go to http://localhost:3000 and you’ll see the default Ruby on Rails: Welcome aboard screen. This is just the index.html file located in the public folder. You can delete this file and I recommend you do if you want to continue. Refreshing the page will give you a nice big fat Template is missing error, which we’re about to fix.