views:

173

answers:

2

I'm looking for a restful way of passing through options to a service. Right now I have a devices resource accessed in standard rails manner with:

map.resources :devices, :member => [:historical]

So I can get my device with /devices/:id and I can get historical data with /devices/:id/historical

I'd like to actually add a param onto the historical URL that specifies a range, so when I query for historical data, i can get it back by hourly, daily, weekly, monthly. Something like /devices/:id/historical/:range

Is there a way to modify my route setting above to accommodate this? Or do I just have to pass it in like /devices/:id/historical?range=hourly

I'd prefer the former, but I'm not sure if that's breaking Restful conventions or what the best way to go about this is.

+1  A: 

Having range as a path segment, or a query parameter are both potentially RESTful.

The question is really a design issue. Do you want to model the historical data as a single resource with a parameter, or do you want to model multiple resources? This is the same kind of decision that we make when doing OO design. Do you want one class with type property or a bunch of subclasses? Or database design, do we store the data in multiple tables or one table with a discriminator column?

As long as you use the HTTP verbs correctly to manipulate that resource then you will not violate the relevant REST constraints.

Darrel Miller
+1  A: 

I think that really your question comes down to how to know when it's appropriate to represent something as a resource and when to parameterize it using a query string.

I don't know your domain, but from your question it appears that historical data about a device is a resource and that accessing subsets of that data through a range is best represented as a query string, in the same way that you might paginate a large list of items.

Something else to consider is caching, because if you want to page cache each range individually then you will have to use path segments within the route i.e. :range. That way Rails will generate a unique HTML file on disk to represent that range. If you use a query string then it will effectively get ignored and the same HTML file will be returned for different ranges.

John Topley
so out of interest sake then, do you know how I can add that :range to my historical URL, save writing a separate named route. Is there an option to add params to a route in Rails? I haven't found one
brad
@brad you can pass parameters for the url helpers link_to historical_reports_path(device, :range => 'daily')
Mereghost
Ya I'm aware of that, i'm more interested in adjusting the route itself so that it's not a query string, but a resource identifierso, not /devices/:id/historical?range=daily but /devices/:id/historical/:range
brad
I don't understand your question. Just do what you have: `/devices/:id/historical/:range`
John Topley
ok, right now with map.resources :devices, :member => [:historical] I have the url: /devices/:id/historical so I don't know how to modify that route definition to know that the param after 'historical' is called :range
brad
I think you'll have to add it as a separate named route.
John Topley