Simplify your URLs with conditions

Posted by Luke
on Thursday, March 22

Have you ever wondered how Rails’ RESTful Routes create URL mappings that can only be accessed by certain HTTP methods?

For example, map.resources :users creates an entire set of named routes that can only be accessed with the appropriate HTTP method. GET’ing users_path maps to a different controller method than POST’ing to users_path (see the documentation and the free PeepCode cheatsheet for more details).

The answer is the undocumented :conditions parameter for ActionController::Routing::RouteSet#add_route. It’s kind of sad when the best documentation available for one of Rails’ most powerful features is from a Python re-implementation.

But once you know it’s there, it’s really easy to use :conditions to create your own HTTP-savvy routes, simplifying your URLs in the process.

Let’s say you’ve got a form that sends e-mail. You need two actions: one to show the form, and one to send the mail.

1
2
3
4
ActionController::Routing::Routes.draw do |map|
  map.show_form '/contact', :controller => 'contact', :action => 'show_form'
  map.send_mail '/send', :controller => 'contact', :action => 'send_mail'
end

But with :conditions, you can consolidate these two URLs into a single URL that responds differently to GET and POST requests.

1
2
3
4
ActionController::Routing::Routes.draw do |map|
  map.show_form '/contact', :controller => 'contact', :action => 'show_form', :conditions => {:method => :get}
  map.send_mail '/contact', :controller => 'contact', :action => 'send_mail', :conditions => {:method => :post}
end

This keeps your URLs simple, and ensures that your methods are hit with the proper HTTP verb.

P.S.: Interested in how RESTful routes work? Check out the code and take a look at the routes it generates, as produced by the Route Navigator plugin.

Comments

Leave a response