Beginners Tutorial: Routing in Rails 2.0 (with REST) – Part 1 of n

Part 2

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.

RoutingInRails

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:

Welcome

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:

Empty Album List

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…

Album List

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.Routing Error

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…

Part 2



Advertisement

83 thoughts on “Beginners Tutorial: Routing in Rails 2.0 (with REST) – Part 1 of n

  1. 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.

  2. 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.

  3. Pingback: Beginners Tutorial: Routing in Rails 2.0 (with REST) - Part 2 of n « Daryn’s Blog

  4. Pingback: Ruby on Rails Tutorials (version 2.0+ compatible)

  5. Excellent tutorial. Thank you very much. I am e newbe and this tutorial helps me e lot. I’ll follow all parts eagerly.

  6. Great Tutorial!!

    What do use to present the source code? Pastie? Some wordpress plugin?

  7. This is really funtastic tutorial. Iwas stucked in problem following another tutorial but this helped me a lot.

  8. Pingback: Paper Bits – links for 2008-04-23

  9. Pingback: Routing in rails « Rails-o-matic

  10. 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

  11. Pingback: This Week in Ruby (May 12, 2008) | Zen and the Art of Programming

  12. 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.

  13. Nice articles!
    Could I translate it into Chinese so that more readers could benifit from it?

  14. Pingback: Weerasak.com » Article: Beginners Tutorial: Routing in Rails 2.0 (with REST)

  15. Small typo in source code for “setup.rb” when you’ve emptied it of the default routes – you have a hanging .

    Thanks for tutorials 🙂

  16. Hi Diabolo, where is the hanging . ?
    I did notice that a pre tag had snuck in, I removed that. But where is the . ?
    -Thanks

  17. 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?

  18. Pingback: railing systems

  19. You can run “rake routes” to get a list of the mapped routes, no need to bother with reloading the console.

  20. Thanks a lot for this great tutorial, it really simplifies the Routing topic for a newcomer like me.

    Thanks again.

  21. Pingback: Short-listed!?! « Project Entropy

  22. Pingback: links for 2008-07-21 | svenkubiak.de

  23. 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!!

  24. Pingback: Tutorials in Routing in Rails 2.0 | ActivoRicordi Captain's log

  25. Pingback: C4 » Blog Archive » Routing in rails

  26. Pingback: C4 » Blog Archive » Link Shot #1

  27. Nice Tutorial.

    For getting updates routes quickly, try:

    ruby script/runner “puts ActionController::Routing::Routes.routes”

    on the console / command line 🙂

  28. 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.

  29. Very much appreciated – looking forward to getting to Restful stuff – but glad of thorough introduction to basics first.

  30. Pingback: Ian On The Red Dot :: Routing In Rails

  31. 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.

  32. You can (at least with Rails 2) reload the application into your console with “reload!”, so you don’t hae to exit and restart.

  33. Pingback: rails routes | the evolving ultrasaurus

  34. Pingback: Ruby on Rails Tutorials (version 2.0+ compatible) | Seeds To Trees

  35. 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.

  36. nice tutorial, thx for writing.

    just didn’t get exactly how the thing with format works out of your explanation.
    the REST is clear 😉

  37. reload! works, there is no need to exit irb

    >> reload!
    Reloading…
    => true
    >> puts rts.routes
    => nil

  38. Pingback: Rails routes | Thinks Free

  39. Pingback: Jin-Kang CHENG » Rails routes

  40. 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

  41. 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.

  42. 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.

  43. Pingback: Rails: Routes in “irb” « Jin-Kang Cheng

  44. Pingback: Understanding RoR Routing » Rodrigo Reyes Blog

  45. 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.

  46. Pingback: Escludere una directory da passenger | pragmatico

  47. Pingback: Writing RESTful API | Five AM Software

  48. Pingback: Rails RESTful Tutorial | Status-Star

  49. Pingback: Routing in Rails – resources | Status-Star

  50. Thank you so much, this was what I was looking for, a clear way to start with Ruby in Rails

  51. Pingback: Huge post on Rails routing | WP Cookbook

  52. 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!

  53. 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.

  54. Pingback: Gem filled train tracks | Lightbulb Manifesto

  55. 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?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s