An Introduction to Routing
A short sharp introduction to routing in Merb, focussing on some of the more interesting aspects. This tutorial will later be followed up with more detailed articles focussing on specific aspects of the router, but for now this will help get you started.
Merb’s router is extremely powerful and flexible. On first-blush it might seem a wee bit scary, but trust me, once you know the basics it’s straight-forward.
Consider some of the criteria you might want to use in your routings;
- Path
- Subdomain
- Protocol
- Port number
- Results of a RegEx match on a URL
Merb’s routing holds the answers! It can handle all of this with it’s nice DSL. So, for the sake of illustration I might run through a few examples from an application I’m currently working on. I’m not going to over every feature listed above, for now I’ll keep it simple. Cool? Ok, let’s make like a sausage and roll!
Simple Stuff
First something really simple; sending requests on the root url to a particular controller and action. First we match() the url. Then we specify the controller and action we want to send it to. OK… so not that clever.
r.match('/').to(:controller => 'home', :action => 'index')
Another simple one to demonstrate the use of place holders in the match. Any parts of the URL that appear where you specify a place holder will then be available in the routing.
r.match('/:controller/:action').
to(:controller => ':controller', :action => ':action')
Just to demonstrate, you could have a weird URL scheme like this:
r.match('/:id/:controller').
to(:controller => ':controller', :action => 'show', :id => ':id')
Getting Awesome
Now time to show some awesomeness. You can send requests to controllers that live in a particular module based on the subdomain.
r.match('/:controller/:action', :subdomain => ':subdomain').
to(:controller => ':subdomain/:controller', :action => ':action')
This would be perfect for redirecting the requests via an admin subdomain. So requests to admin.domain.com/users would get sent to the controller/action Admin::Users#index. Nice!
I should also point out that you can also easily turn each one of these route declarations into a named route. Like so:
r.match('/login').to(:controller => 'users', :action => 'login').name(:login)
You just call #name at the end of the route declaration and pass in a symbol which will be the name you can then use in your #url calls inside controllers and views.
Ok, one last cool thing. You can match to a segment of a URL, then define a bunch of sub-matches. This is done by passing a block to the match method.
r.match('/admin') do |admin|
admin.match("/:controller").
to(:controller => "admin/:controller", :action => 'index')
admin.match("/:controller/:id").
to(:controller => "admin/:controller", :action => ":show", :id => ':id')
%w(edit delete).each do |action|
admin.match("/:controller/:id/#{action}").
to(:controller => "admin/:controller", :id => ":id", :action => action)
end
end
So what I’ve done here is match against /admin then we go onto our sub-matches. First the controllers index action. Then with an id, we map to the show action. Finally we map to the new and delete actions. This isn’t a real world example, since we’re only crudely emulating RESTful routing, but it shows how flexible you can be with matching parts of a url.
In my next Merb(ivorian) post I’ll go into a little more detail about the resources route declarations and doing some more clever stuff with ports and sub-domains. OH YEA.
Comments
On June 02, 2008 at 21:27 taerb says:
One of my favorite things is Merb’s handling of different keys for restful resources. Take a blog post for instance, instead of having the id in the url, you could have a permalink.
r.resources :posts, {:keys=>[:permalink]}Great for SEO reasons, and doesn’t break the hell out of the framework, so you still get your named resource routes.
Sign in to add your comment