toolmantim

Merb Routing in 0.5

January 22, 2008 17:43 (Sydney Australia)

Merb’s routing shiznits needs some serious documentation love. Whilst I have a shot at getting some proper docpatches together here’s an overview of how to use routing in Merb 0.5.

Path Matching

The match method defines how to route requests to controllers and actions.

r.match("/contact").
  to(:controller => "info", :action => "contact")

You can define placeholder parts of the url with :symbol notation. These placeholders will be available in the params hash of your controllers. For example:

r.match("/books/:book_id/:action").
  to(:controller => "books")

The placeholders can also be referenced in the to portion of the route if necessary:

r.match("/admin/:module/:controller/:action/:id").
  to(:controller => ":module/:controller")

Named Routes

Use the name method on a route to give it a name:

r.match("/contact").
  to(:controller => "info", :action => "contact").
  name(:contact)

You can then easily reference the named route from controllers and views:

url(:contact) # => "/contact"

Namespaces

Namespacing routes with namespace is a convenient way of specifying both the :path_prefix and :name_prefix options:

r.namespace :admin do |admin|
  admin.match("/roles").
    to(:controller => "roles", :action => "index").
    name(:roles)
end

Reference a namespaced route by prefixing the route name with the namespace:

url(:admin_roles) # => "/admin/roles"

Resources

You can use Rails-like resource routing with resources:

r.resources :posts

The routes generated are named after their resources:

url(:posts)       #=> "/posts" 

@post = Post[1]
url(:post, @post) #=> "/posts/1"

You can nest resources using the same block syntax used for namespacing:

r.resources :posts do |p|
  p.resources :comments
end

To refer to a nested resource route simply use the child resource’s name. Notice in the following example there’s no need to specify the :post_id parameter as it’s automatically inferred from @comment.

url(:comment, @comment) #=> "/posts/1/comments/2"

If you prefer the Rails 2 style of namespacing nested resources simply specify the name_prefix on the child resource:

r.resources :posts do |p|
  p.resources :comments, :name_prefix => "post_" 
end

Comments

Mr eel

Nice one man.

The router has gotten a lot of love lately with stuff like namespaces. It’s nice to have an overview I can point other people to.

Thanks!

Luis Lavena

I agree with Mr eel,

A document of Merb routing is quite useful :-)

Thank you for taking the time to post this! (shared and starred under Google Reader)

Tony Pitale

Is it possible to match patterns in a match, e.g.:

r.match(’/report/:id’).where(:id is an integer).to….?

Tim Lucas

@tony: Yep! From router_spec.rb:


# Use square-bracket notation to replace param results with captures from the path
r.match(%r[^/movies/(\d+)-(\d+)-(\d+)$]).
  to(:controller => "movies", :movie_id => "[1][2][3]", :action => "show")

d

Any idea what we can pass as conditions to match()? I wanna be able to match on POST or GET , if I can.

Tim Lucas

Yep. Again from router_spec.rb:

r.match("/login", :method => "get").
  to(:controller => "sessions", :action => "new").
  name(:login)
r.match("/login", :method => "post").
  to(:controller => "sessions", :action => "create").
  name(:login)

Which reminds me of Daniel Neighman’s sweet router hack he posted not long ago.

AndrewO

Great post, Tim. I was wondering though: can Merb do route globbing (“*path” style)?

Sergio Oliveira

I want to call MyModule::Core::MyController…

Tried everything but nothing works!

How?

Star Trader

When using resources, how would one get the url to edit a resource?

Taking you example above, what url() function would produce ’/posts/edit/1’

Tim Lucas

@Star Trader:

url(:edit_post, @post)

taerb

what i dont get is the url() for delete on a resource, and i see it you can do one of two things.

1) you could break restful design, and rename your destroy method to delete, and have your call look like this

  link_to 'Delete', url(:delete_post, post)

2) Or you could keep things restful and wrap your delete in a


  form_for(:post, :action => url(:post, post), :method=>:delete )

of course you would add the submit button and such.

Is there a third option I am not seeing?

Tim Lucas

@taylorredden Not sure what you’re asking. There’s really no URL to delete a resource, you just perform a DELETE on the resource itself (your example 2)

To comment on this article you must have javascript enabled.