Tuesday, December 11, 2007

Rails: Route Globbing

Today I was working with some code that utilized the same array on various pages. After evaluating a few options I decided that Rails Route Globbing was probably the best solution for passing the array of integers from page to page.

I originally learned about Route Globbing from David Black's Rails Routing. Route Globbing works by grabbing everything past a certain point in a url and storing the elements in an object that behaves like an Array.

For example, the following route sets the user_id and feed_ids parameters based on the url.

map.specific_feeds '/users/:user_id/feeds/*feed_ids', :controller => 'feeds', :action => 'index'

# navigating to http://a.domain.com/users/23/feeds/2/24/55/89 will result in
# params[:user_id].inspect # => "23"
# params[:feed_ids].inspect # => ["2", "24", "55", "89"]

The above behavior is nice for grabbing values, but it's also useful for passing on the values of an array when creating links and forms.

<!-- in a view, given the above route you can create a link with -->
<%= link_to "next", specific_feeds_url(params[:user_id], params[:feed_ids]) %>

<!-- or you can create a form with -->
<% form_tag specific_feeds_url(params[:user_id], params[:feed_ids]) do %>
<% end %>

Thankfully, Route Globbing usually just works, but there is one gotcha for Rails <2.0: The glob must appear at the end of the route. Once an asterisk is used everything after must be part of the glob.

# No Good
map.specific_feeds '/feeds/*feed_ids/users/:user_id', :controller => 'feeds', :action => 'index'

# Good
map.specific_feeds '/users/:user_id/feeds/*feed_ids', :controller => 'feeds', :action => 'index'


As Brandon points out in the comments, Rails 2.0 allows you to put the glob anywhere in the route.

2 comments:

  1. Anonymous8:32 AM

    but there is one gotcha: The glob must appear at the end of the route

    That's actually not true. I was under that impression until yesterday when I was working on some weird routes and found out (in Rails 2.0, at least) that the glob doesn't have to be at the end of the route.


    map.tagged_articles 'tagged/*tags/articles', :controller => 'resources', :action => 'index'

    ReplyDelete
  2. Anonymous12:46 PM

    That's cool. I've updated the post to reflect the difference between the versions of Rails.

    Cheers, Jay

    ReplyDelete

Note: Only a member of this blog may post a comment.