Creative Commons License photo credit: alexanderdrachmann

I was recently helping a friend out with his Rails project and we were trying to figure out the best way to handle queries in a RESTful Rails app, i.e. returning a subset of items meeting certain conditions. After a bit of poking around, here’s what looks like the most promising convention to follow (please post a comment if you disagree with the conclusion described here).

We had two inter-related questions:

  1. What should a query URI look like in a RESTful environment?
  2. What Rails coding pattern should be used to respond the RESTful query?

What should a query URI look like in a RESTful environment?

The main choices here seemed to be between including the query parameters in the path or placing them after a question mark, e.g.

/items/large or /items?size=large

The answer is: use the latter form: /items?size=large

[Note: the exception would be if you have a resource called LargeItem in your app. In that case you’re really just looking at a standard REST collection GET which should be handled by the index method of your LargeItem controller.]

What Rails coding pattern should be used to respond the RESTful query?

So you’ve now opted for the URIs of the form /items?size=large. What code do you need to respond to these queries?

If you’re using the default Rails 2.0 RESTful resource scheme, queries will now be routed to the index method of your Item controller and your query parameters will be accessible via params, e.g. params[:size].

Your index method needs to return different subsets of your items collection depending on which (if any) query parameters have been passed in. For now I’ll probably put the logic to sort between the different cases in the controller, but it might be better to move it into the model (following the skinny controller, fat model pattern). Any thoughts on this?

How to link to specific queries

You can link to specific queries using something like this:

items_path(:size => ‘large’)

References:

Many thanks to the following sources:
http://groups.google.com/group/geo-web-rest/browse_thread/thread/c1f46a0fa1731047
http://woss.name/2007/07/22/convention-for-restful-search-in-rails/
http://softiesonrails.com/2007/11/29/simulating-xml-requests-with-a-check-box

Categories: Technology

2 Comments

Peter Jones · April 21, 2008 at 4:52 pm

By using an if statement in the controller, as detailed below, it is possible to move code to the model. This doesn’t avoid sorting between the different cases in the controller, but it does make the code in the controller more readable and cuts down on the code there.

So linking to the specific querie using the following:

‘great’) %>

will link to this url /items?average_rating=great which will access the following if statement in the items_controller:

def index
if params[:average_rating] == “great”
@items = Item.find_items_that_are_great
else
@items = Item.find(:all)

end

The else part of the statement returns RESTful results as expected from /items if the initial condition/querie is not met.

However, if the first condition of the if statement is met/true “find_items_that_are_great” in models/items.rb returns results in accordance with the following which is the specific querie:

def self.find_items_that_are_great
find(:all, :order => ‘score desc’, :conditions => ‘score>4’ )
end

The code is implemented here:

http://isitgreat.heroku.com/items?average_rating=great

Buzzterrier · October 22, 2008 at 7:08 pm

So how do your format >, =, <= queries?

/items?size=>36

??

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *