An Introduction to Routing
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 make your voice heard