Beginners Tutorial: Routing in Rails 2.0 (with REST) - Part 1 of n
About this series
This is a series for beginners wanting to learn about routing in Rails 2.0. This first post is aimed at exploring the behaviour of routing in Rails. It examines what happens when the routing system is given a certain URL. Future posts will examine the ‘hows’ and ‘whys’ of this behaviour. The plan is to start with the basics and move towards the advanced topics. There is only a brief mention of RESTful routing in this post. I plan to delve deeper into that topic at a later stage.
I will continue with this series only if there is a demand for further posts, and if time permits. If nobody is interested, then I will come up with a new topic and start pestering the world all over again!
Introduction
The routing subsystem is at the heart of a Rails application. By looking at the following image, we can see the role of the routing system.
The diagram is a modified version of a diagram found in Flexible Rails.
As the picture depicts, in a Rails application the process begins with a request from the browser. This request is passed into the Rails routing system. The routing system examines the request and is able to determine the following information:
- Which controller to instantiate
- Which action (method) to invoke on that controller
- The parameters, if any, to pass into the action
When receiving a correctly formatted request URL the routing system will instantiate the specified controller, call the appropriate action and pass in the supplied method parameters, if required. The controller will then perform the necessary action and Rails will render the relevant view. This will result in the browser receiving a response and the round trip is complete. This is oversimplified, but it does show the importance of the routing system.
If the request is not in the correct format the routing system may not be able to infer the correct action to take. Therefore it is important that the format is correct. We are in luck as the Rails routing system also helps us to generate requests in the correct format.
In short, the routing system has two main functions:
- Interpreting a request URL
- Generating a request URL
The routing system performs these functions by using routing rules, defined in Ruby code as opposed to XML. The rules can be found in the config/routes.rb Ruby file. Each rule is used to both interpret and to generate a related request URL.
I could go into more theory here but, as with many things, the best way to get to grips with routing is to do it!
The Practical Part…at last
When I wrote this post, I was using Instant Rails as per my suggestion in a previous post.
Preparation
Issue the create command to create a rails application:
C:\InstantRails-2.0-win\rails_apps>rails -d mysql music_store
Rails does its thing…
Then we create the database…
C:\InstantRails-2.0-win\rails_apps>cd music_store C:\InstantRails-2.0-win\rails_apps\music_store>rake db:create:all (in C:/InstantRails-2.0-win/rails_apps/music_store)
Do a quick test to make sure things are in order.
C:\InstantRails-2.0-win\rails_apps\music_store>ruby script\server => Booting Mongrel (use 'script/server webrick' to force WEBrick) => Rails application starting on http://0.0.0.0:3000 => Call with -d to detach ... output … ** Mongrel 1.1.2 available at 0.0.0.0:3000 ** Use CTRL-C to stop.
Start a browser and navigate to: http://localhost:3000/
Make sure you expand the ‘About your application’s environment’
You should see the standard welcome screen:
If you are experiencing problems, make sure your proxy is turned off.
Perform some scaffolding to create an ‘Album’.
ruby script\generate scaffold Album title:string review:text
Rails goes again…
In the last line of the output we see:
route map.resources :albums
Rails has actually created a route for us, it happens to be a RESTful route! We will get to that later. We are just noting it for now, Rails has jumped the gun. RESTful routes are what we want in our application, but first we want to have a good understanding of routes. The best way to understand routes is to experiment with them. Later we will remove that RESTful route, which rails created, and play around with customised routes. We will then explore named routes and move back to using RESTful routing.
Before doing all of that, lets get our Albums section up and running.
Run the rake migrate task
C:\InstantRails-2.0-win\rails_apps\music_store>rake db:migrate
Browse to this URL: http://localhost:3000/albums
You should see:
Let’s use our shiny new Rails application to add a few albums. Create three albums and do not delete these first three. Later on we will assume that you have three albums having database IDs of 1, 2 and 3. Create and delete a forth one if you like, but don’t delete the first three Albums. You can enter any data, try to show more taste than I did…
We are not going to use any CSS or partials at this point, that is not the point of this tutorial. OK, let’s get back to routing!
Experimenting 1 - View the generated routes
The objective of this experiment is to view the generated Ruby code which defines the generated routes. We then explore the behaviour of these routes. This will help us gain some insight into how the routing works. We will use the IRB to perform these actions.
Open up the config\routes.rb file to see the actual code that defines the routes. You should see code as depicted below, with additional comments. You may want to leave the comments so that you can read them as we move on.
ActionController::Routing::Routes.draw do |map| map.resources :albums map.connect ':controller/:action/:id' map.connect ':controller/:action/:id.:format' end
Rails has generated three routes for us, these are the routes our application is currently using. Let’s examine the behaviour of these routes. A good way to do this is by using the IRB.
C:\InstantRails-2.0-win\rails_apps\music_store>ruby script/console Loading development environment (Rails 2.0.2) >> rts = ActionController::Routing::Routes
Expect a console output splat! Let’s get some output in a nice format.
>> puts rts.routes
1 GET /albums/ {:action=>”index”, :controller=>”albums”}
2 GET /albums.:format/ {:action=>”index”, :controller=>”albums”}
3 POST /albums/ {:action=>”create”, :controller=>”albums”}
4 POST /albums.:format/ {:action=>”create”, :controller=>”albums”}
5 GET /albums/new/ {:action=>”new”, :controller=>”albums”}
6 GET /albums/new.:format/ {:action=>”new”, :controller=>”albums”}
7 GET /albums/:id/edit/ {:action=>”edit”, :controller=>”albums”}
8 GET /albums/:id/edit.:format/ {:action=>”edit”, :controller=>”albums”}
9 GET /albums/:id/ {:action=>”show”, :controller=>”albums”}
10 GET /albums/:id.:format/ {:action=>”show”, :controller=>”albums”}
11 PUT /albums/:id/ {:action=>”update”, :controller=>”albums”}
12 PUT /albums/:id.:format/ {:action=>”update”, :controller=>”albums”}
13 DELETE /albums/:id/ {:action=>”destroy”, :controller=>”albums”}
14 DELETE /albums/:id.:format/ {:action=>”destroy”, :controller=>”albums”}
15 ANY /:controller/:action/:id/ {}
16 ANY /:controller/:action/:id.:format/ {}
The middle column is commonly referred to as the path (also called the relative path). On our local development machine the fully qualified URL of /albums/ is localhost:3000/albums.
Line 1 shows us that if we do a GET using /albums/ the action index will be called on the albums controller. Try it in your browser, use http://localhost:3000/albums/.
Line 7, here the routing system will behave in a similar way as before. To invoke this rule we use a URL replacing the :ID symbol with an existing album ID from the database e.g. /albums/2/edit/. This will result in the edit action being called on the albums controller. The 2 will be made available to the album controllers edit action through the params hash. We can see this if we open the albums controller and look at the edit method:
# GET /albums/1/edit
def edit
@album = Album.find(params[:id])
end
end
Using :id is a convention. We could use another symbol but then we would have to remember to use that in the controller. As you know, it is always better to stick to convention when working with Rails - DHH knows best.You may have noticed some paths ending with format. This can be used to pass a format though to a controller in the params hash, this is similar to the id field. Do not change this symbol, it is a special symbol and must be called :format.One example of using :format would be if we wanted to retrieve XML. Using http://localhost:3000/albums.xml will render xml in the browser, try it. Looking at the albums controller we can see the params[:format] parameter being used.
# GET /albums
# GET /albums.xml
def index
@albums = Album.find(:all)
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @albums }
end
end
As can be seen in the code above, it is the respond_to method that uses the format value to determine the format of the response. At this stage you should be gaining some sort of intuition for Rails routing, right? Now it is time to break our application…
Experimenting 2 - Removing all routes
Open up the config\routes.rb file and delete (or comment out) all the code. Now you should have removed the RESTful route as well as the default route. I will explain the default route (as well as RESTful routes) in future posts. As for now, we are left with an empty file. Behold the naked routes.rb!
ActionController::Routing::Routes.draw do |map| end
Run your application through the browser and you will find that our application is completely broken! It should show the error below.
You can aslo use the IRB to check the status of the routes. I did have some problems seeing the updated routes within the IRB. I found that I needed to exit the IRB, then do the ‘load and instantiate’ dance again…
>> exitC:\InstantRails-2.0-win\rails_apps\music_store>ruby script\console Loading development environment (Rails 2.0.2) >> rts = ActionController::Routing::Routes => #<ActionController::Routing::RouteSet:0x3ed12e8 ... more output ... >> puts rts.routes => nil
Perfect, no routes as we expected…
If someone can help with this issue of needing to exit the IRB, I am all ears? If needing to exit the IRB unavoidable, a small script may be handy…
At this stage we have a broken Rails application. In the next post we will set about fixing the music_store application, while doing that we will learn different aspects of routing in Rails.
I realise this is poor to leave you with a broken application, I will attempt to make up for it in the next post…
The End (of part 1)
Well, that is it for the first post. Please let me know if you found this useful. As I said before, I will only continue with this series if there is a demand. Please suggest topics you would like me to cover.
I have a general plan, future posts will cover:
- The anatomy of routing rules
- The default route
- Static routes
- Wild card\Receptors
- RESTful routing
If people are finding this pace too slow, I might skip directly yo RESTful routing, but this all depends on your feeback.
Thanks, I hope this was useful to you…




March 18, 2008 at 4:41 pm
This is a great tutorial, and I’m eagerly awaiting more on routes.
Thanks!
March 18, 2008 at 4:55 pm
Great beginners tutorial! I’ve been looking all over the web for a good RESTful rails 2.0 tutorial. Thanks!
I have a project to make. Maybe you can help me with something. First of all, I’m new to ruby and rails but have programmed in PHP. I’m trying to make a max count for a serial number usage using an xml or url (or if you can recommend any other) request from a client application. I would like to update the database count until it reaches the max amount, then reply a message or code in return. Any input would be appreciated. Thanks in advanced.
March 18, 2008 at 6:26 pm
Please continue….
March 24, 2008 at 7:24 pm
Hi all, thanks for the enthusiasm.
You will be pleased to know that I have just about completed part 2.
It will be up shortly - I have been delayed due to SPA.
herb, I would recommend using XML. Make the calling application provide some form of unique ID. The controller should update the database and then return the required XML. You could have the user brows a URL and click generate, then you provide a key to be copied and pasted, it is really up to you.
March 25, 2008 at 6:32 pm
[...] (with REST) - Part 2 of n Thank you to all of you who took the time to give me feedback on part 1. Most of the feedback was positive. A friend of mine suggested that I drop the sound effects and [...]
March 25, 2008 at 6:50 pm
Part 2 is now out…
April 8, 2008 at 10:28 pm
[...] guide/Learning Routes part 1 part [...]
April 19, 2008 at 2:13 am
Excellent tutorial. Thank you very much. I am e newbe and this tutorial helps me e lot. I’ll follow all parts eagerly.
April 19, 2008 at 7:59 am
Great Tutorial!!
What do use to present the source code? Pastie? Some wordpress plugin?
April 19, 2008 at 1:01 pm
Thanks Lorenzo, and this is what I use for formatting the source code http://wordpress.com/blog/2007/09/03/posting-source-code/
April 20, 2008 at 7:42 am
This is really funtastic tutorial. Iwas stucked in problem following another tutorial but this helped me a lot.
April 27, 2008 at 10:46 pm
[...] Beginners Tutorial: Routing in Rails 2.0 (with REST) - Part 1 of n « YAB Introduction: how rails uses the routes.rb file to create named routes and paths, and RESTful URLs. And stuff. (tags: rails howto REST xml @toread) [...]
April 30, 2008 at 8:31 am
[...] quite into details and which is very informative for beginners like me. The tutorial is splitted in part 1 and part 2. Part 3 is yet to come, but I hope it will be soon! Thanks to Daryn Holmes for this [...]
May 7, 2008 at 2:29 pm
gave the concepts well . i stubled upon this while i was wondering why i was not getting
my action from the controller when url invoked was controller/action format. after i gone through this i understood. but liked the old style routing and wanted to use old style until i make some progress, I did it by commenting out the resources lines. the tip i found from google forums. waiting for your third part eagerly. to wrap up the knowledge on this routing puzzle. Thank you
May 7, 2008 at 2:38 pm
Hi Narender, part 3 is out, you can find it here.
May 12, 2008 at 7:53 pm
[...] on Routing in Rails 2 was recently published. If you haven’t done so, follow the links to part 1, 2, 3 and [...]
May 13, 2008 at 12:34 am
Guess what - to reload Rails in the console just say
reload!
May 13, 2008 at 10:12 am
reload! does not seem to work. I tried that while I was making this post and I tested it again now. This might be because I am ’stuck’ on Windows. This is not an InstantRails problem, as I am not using that any more.
May 14, 2008 at 2:10 pm
Nice articles!
Could I translate it into Chinese so that more readers could benifit from it?
May 17, 2008 at 2:59 am
[...] Tutorial: Routing in Rails 2.0 (with REST) - Part 1, 2, 3 and 4 by darynholmes This is a series for beginners wanting to learn about routing in Rails [...]
May 19, 2008 at 2:57 pm
Small typo in source code for “setup.rb” when you’ve emptied it of the default routes - you have a hanging .
Thanks for tutorials
May 19, 2008 at 3:19 pm
Hi Diabolo, where is the hanging . ?
I did notice that a pre tag had snuck in, I removed that. But where is the . ?
-Thanks
June 1, 2008 at 7:28 pm
Leon, sorry for not replying. I just noticed your comment in my spam box. You are welcome to translate it. Where could people find the translated version?
June 3, 2008 at 11:47 am
[...] therefore are out of date. The Routing system is at the core of Rails. This tutorial teaches you frohttp://darynholmes.wordpress.com/2008/03/15/beginners-tutorial-routing-in-rails-20-with-rest-part-1-…Creative Railing Systems - B.W. Creative Wood Industries Ltd.railing systems interior products [...]
June 11, 2008 at 12:24 am
You can run “rake routes” to get a list of the mapped routes, no need to bother with reloading the console.
July 1, 2008 at 6:41 am
Thanks a lot for this great tutorial, it really simplifies the Routing topic for a newcomer like me.
Thanks again.