Routing in Rails


One aspect of web development developers would like control over is the URL structure. In most web development languages, the URL is intrinsically tied to the folder and file structure.

Rails–although it also allows use of this structure for static files, through the public directory–differs on two counts. First, it defaults to a www.yoursite.com/controller/action style of routing, based on actions in different controllers. And second, Rails provides control over routing, allowing you to map virtually any URL to different actions.

Open up your config/routes.rb file. Among other things, you’ll see this at the bottom:

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

This is where Rails, by default, maps the URL to /controller/action. Rails tries to map routing from the top of the file to the bottom, so leave this route at the bottom–it’s the default, the fall-back.

How do you route the root of your site to an action? For example, if people browse to www.yoursite.com/, you’d like to take them to a specific URL.

To do that, simply write the following:
map.root :controller => "SomeController", :action => "someAction"

(If you’re still using Rails 1.2, you can achieve the same thing by mapping “/” to a controller and action.)

Routing is great–you can specify a URL with variables in it, and map to different controllers, using those variables. Say you want to create a blog, and you want a URL like “myblog.com/2008/03/19/post-slug”. How can you do this with routing?

Easily. Check out the following route:
map.connect "/:year/:month/:day/:slug", :controller => "Posts", :action => "show"

If you browse to myblog.com/2008/03/19, it’ll activate the show action of the Posts controller. Inside params, you’ll have four keys–year, month, day, and slug–and you can use those to pick out the right post to display.

Note that this route will even match “myblog.com/pink/furry/hamster/blah”, mapping :year to “pink”, :month to “furry”, :day to “hamster”, and :slug to “blah”–which is why you need to validate your params values and redirect, accordingly, on errors.

And that really summarizes routing–you can route virtually any URL, and you can specify variables, but not types–so each route must be distinct. The following two routes can’t co-exist:

map.connect "/:post-slug" :controller => "Posts", :action => "show"
map.connect "/:page-slug", :controller => "Pages", :action => "show"

Think about it. If you navigate to /routing-in-rails, is that a post slug or a page slug? It can match both. Rails, as we said earlier, matches routes from top-down–so it’ll match the post controller, not the page controller.

To summarize, Rails provides a powerful and flexible way to control the URL structure via routing; routes are matched from top to bottom; but routing variables are not typed, so you always need to watch out for two routes that would match the same URL.

You might ask, “how can we solve the problem above?”–that is, keeping pages and posts and mapping both to a similar URL? This is something desirable to blogging platforms.

One solution is “make posts and pages the same type.” This is the solution Wordpress, a PHP-based blogging platform, uses.

The second solution is to use different URLs–map articles to /articles/slug, and pages to /pages/slug. This is the solution RailsRocket takes.

The third solution is to write a little more code. Route the request to the posts controller; if the action can’t find a post with that slug, then route the request to the pages controller; if it finds it, then the URL was for ra page, not a post. If the URL is invalid, neither action will be able to find the URL.

But with the third approach, there’s always the possibility that a page and post will have the same post-slug–in which case, the first route will take precedence. So in the end, it’s really up to you to figure out what works best for your needs and requirements.

Tags: , , ,     Posted in Development

Rate this article:
1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...

Further Reading

  • No related posts

Leave a Reply