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.
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…
This is a great tutorial, and I’m eagerly awaiting more on routes.
Thanks!
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.
Please continue….
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.
Pingback: Beginners Tutorial: Routing in Rails 2.0 (with REST) - Part 2 of n « Daryn’s Blog
Part 2 is now out…
Pingback: Ruby on Rails Tutorials (version 2.0+ compatible)
Excellent tutorial. Thank you very much. I am e newbe and this tutorial helps me e lot. I’ll follow all parts eagerly.
Great Tutorial!!
What do use to present the source code? Pastie? Some wordpress plugin?
Thanks Lorenzo, and this is what I use for formatting the source code http://wordpress.com/blog/2007/09/03/posting-source-code/
This is really funtastic tutorial. Iwas stucked in problem following another tutorial but this helped me a lot.
Pingback: Paper Bits – links for 2008-04-23
Pingback: Routing in rails « Rails-o-matic
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
Hi Narender, part 3 is out, you can find it here.
Pingback: This Week in Ruby (May 12, 2008) | Zen and the Art of Programming
Guess what – to reload Rails in the console just say
reload!
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.
Nice articles!
Could I translate it into Chinese so that more readers could benifit from it?
Pingback: Weerasak.com » Article: Beginners Tutorial: Routing in Rails 2.0 (with REST)
Small typo in source code for “setup.rb” when you’ve emptied it of the default routes – you have a hanging .
Thanks for tutorials 🙂
Hi Diabolo, where is the hanging . ?
I did notice that a pre tag had snuck in, I removed that. But where is the . ?
-Thanks
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?
Pingback: railing systems
You can run “rake routes” to get a list of the mapped routes, no need to bother with reloading the console.
Thanks a lot for this great tutorial, it really simplifies the Routing topic for a newcomer like me.
Thanks again.
Pingback: Short-listed!?! « Project Entropy
Pingback: links for 2008-07-21 | svenkubiak.de
AWESOME, FANTASTIC… A+, highly reccommended
Super tutorial, thanks a lot!
Excellent tutorial very usefull
Thanks a lots!
Nice work. Please continue..
For route reloading, have you tried ActionController::Routing::Routes.reload?
Excellent set of articles!! Really helpful after reading several books and tutorials it is the first time I really understand routing and the use of config/routes.rb
Thanks and keep them coming!!
Pingback: Tutorials in Routing in Rails 2.0 | ActivoRicordi Captain's log
Great tutorial, Really helpful a newbie like me. Because I don’t really understand about routing.
Thank’s very much.
great tutorial
it makes things much clearer for beginner when working with rails.
thanks very much.
nice tutorial!
Rails is going to make my coding life much easier!!
http://12tb.com
use
>> reload!
to reload irb.
Pingback: C4 » Blog Archive » Routing in rails
Pingback: C4 » Blog Archive » Link Shot #1
Nice Tutorial.
For getting updates routes quickly, try:
ruby script/runner “puts ActionController::Routing::Routes.routes”
on the console / command line 🙂
thanks for d post!!!
i have been looking for tutorials like this and i am glad to found one.
i look forward to read on other topics as well.
Very much appreciated – looking forward to getting to Restful stuff – but glad of thorough introduction to basics first.
Pingback: Ian On The Red Dot :: Routing In Rails
Hi,
Can you also post something explaining nested routes.
Very useful tutorial. Thank you.
Forget about reloading irb, though, just > rake routes. Easy.
Awesome tutorial. The best(I’ve read) on routes.
Would love to see tutorials on topics like the concept of filters, before / after fiters, how they come into picture, some arcane methods like lambda, respond_to and particularly how the respond_to block in AlbumController#index works would be more helpful.
Once again Thank you for spreading the knowledge.
Sanjay.
You can (at least with Rails 2) reload the application into your console with “reload!”, so you don’t hae to exit and restart.
Pingback: rails routes | the evolving ultrasaurus
Pingback: Ruby on Rails Tutorials (version 2.0+ compatible) | Seeds To Trees
i think this is a great tutorial and it would be great if you provide tutorial on other topics like helpers, model and controller. As your method of explaining is far more better then others it will be great to see these topics in your way. You know the vain to press for cure.
nice tutorial, thx for writing.
just didn’t get exactly how the thing with format works out of your explanation.
the REST is clear 😉
reload! works, there is no need to exit irb
>> reload!
Reloading…
=> true
>> puts rts.routes
=> nil
Pingback: Rails routes | Thinks Free
Pingback: Jin-Kang CHENG » Rails routes
Ahaan… I will follow.
Darynholmes,
I need to create a custom method which will do a GET request.
I am using:
map.resources :entities, :member => {:my_custom_method => :get)
Model’s(which is inherited from ActiveResource class) method definition is:
def my_custom_method data
gett :my_custom_method, :params => data
end
Controller code for invoking this method is:
entity = Entity.new()
@en = entity.my_custom_method(params[:entity])
but this is redirecting to
/entities//my_custom_method.xml instead of
/entities/my_custom_method.xml
I wonder how a blank is getting appended in this URL?
Where I am doing wrong?
Thanks
I have notice when I am creating custom method for :POST method then it is working fine. Only when making :GET request blank will be inserted into URL.
Very good job. Keep it going. I am new to Ruby on Rails and found this to be very useful. Suggestion! Try to make it simplier. Example: it would be great if you started you teaching with an example.
EXAMPLE. The developer has developed a web site using rails a link it to be added to the main page called LEARN_RUBY_By_Joe. In the main page of the site you would place a Link_to command. Once you have done this you now need to create a route for the link. Here’s how you would do it.
Pingback: Rails: Routes in “irb” « Jin-Kang Cheng
Pingback: Understanding RoR Routing » Rodrigo Reyes Blog
Perfect tutorial!!. I liked the way of presenting the tutorial on routing.Every concept is explained detailly.
Please keep posting good explanatory tutorials on various topics on rails.
GOOD WORK!!
Only few of them are posting the tutorials in details.
Once again its a very good tutorial.
great tutorial that gives the basic ideas about rails
Excellent. Looking forward to reading the REST of the parts.
Pingback: Escludere una directory da passenger | pragmatico
Pingback: Writing RESTful API | Five AM Software
Pingback: Rails RESTful Tutorial | Status-Star
nice
Pingback: Routing in Rails – resources | Status-Star
Thank you so much, this was what I was looking for, a clear way to start with Ruby in Rails
Test identicon.
Thanks. A little out of date (3.0.5) but still quite useful.
Pingback: Huge post on Rails routing | WP Cookbook
Great Tutorial!!
It’s refreshing to find a resource that actually contains excellent content. Thank you.
magnificent submit, very informative. I wonder why the
opposite specialists of this sector don’t understand this. You must continue your writing. I’m sure,
you’ve a great readers’ base already!
Wear Breathables:I know it sounds like basic sense but the very first item
you need to check off on your list is breathable underwear.
Pingback: Gem filled train tracks | Lightbulb Manifesto
Good Stuff buddy. Simply puy. Thanks.
Fantastic job. Thanks
It’s really annoying when I am trying to read this and the page keeps jumping down to the video ads, losing my place. Anything you can do about that?
Sorry about that, try this: http://devabout.com/?p=35
It is a copy of the original
Also note that this is for Rails 2 – some of it might have changed in the newer versions of Rails