Mr eel

Ye Newbyes Gyde to Routing in Merb

The part of the Merb I’ve found most interesting lately is the routing. A fair number of people will be familiar with the routing in Rails. Have you ever considered how useful it is? For simple cases it does it’s job with no fuss, but if you want to get clever, most of the time you’re just out of luck.

Consider this; how do you route a request based on the subdomain? Can’t. How about based on the protocol? Nope. The port number? Naah. How about using a regular expression to analyze a URL? Shit out of luck my friends.

Merb’s routing holds the answers! It can do all of that with a much nicer syntax in it’s DSL. So, for the sake of illustration I might run through a few examples from an application I’m currently working on — I’m no expert, so these will just be simple ones.

First something real 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')

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.

Posted on November 20th, 2007 | There are 1 comment

Comments

links for 2007-11-22 « Bloggitation on November 22, 2007

[...] Ye Newbyes Gyde to Routing in Merb (tags: ruby merb programming) [...]

Add a comment

All contents © 2005—2007 Luke Matthew Sutton