Rails Misapprehensions: Query Parameters are RESTful

{{{
We were discussing the *design of search resources* in a REST architecture after the REST talk at the EuRuKo. Usually, search resources process GET requests, compute a subset of searched items and return a representation of the respective items.

The following GET request illustrates this.

http://articles/search?type=shirt&color=red&size=s

It’s absolutely common to allow more parameters.

http://articles/search?type=shirt&color=red&size=s& 
  gender=female&limit=10&amount=20&

h3. Where’s the search resource?

Now, let me state two facts about these URLs.

* From a REST perspective, those *two search queries refer to two _different_ resources*. Remember: Resources are “addressed with unique URLs”:http://nicksda.apotomo.de/2010/10/rails-misapprehensions-crud-is-not-rest/, and when URLs differ you’re addressing differing resources.
* Within Rails, this doesn’t matter that much since both URLs are *processed in the same controller*. This is cool. A controller per definition is meant to expose a set of resources.

h3. Long URLs and REST

After having discussed the meaning of _resources_ the question that came up was

“Isn’t such a long URL with lots of query parameters comparable to clumsy XML-RPC arguments?”

Well, I’d say: *No way.*

* Dynamic resources have to *receive input in a certain manner* – this makes them dynamic. Query parameters were designed to let users specify parameters. There’s nothing wrong with allowing input.
* However, if _you_ decide your URLs are getting too long _you_ have to *redesign your search resource architecture!*

h3. Exposing named queries

The “REST cookbook”:http://oreilly.com/catalog/9780596801694 – a fantastic write-up which I do strongly recommend – suggests to identify commonly used search criterias and *expose those queries as separate resources*.

Say we’re annoyed with the long “search red female shirts” URLs. Why not donate a dedicated resource?

http://articles/shirts/female?color=red&size=s

While this is just an example, it demonstrates how *commonly used parameters were consolidated in a new URL base*. Again, from the REST point-of-view, this points to a completely separate resource.

However, in Rails, this can simply be mapped to the search controller while providing the remaining parameters in the route definition.

match 'articles/shirts/female' => 'articles#search', 
  :defaults => { :gender => 'female',
                   :type => 'shirt' }

h3. Controllers and Resources

Don’t give me a hard time about the routing – what I wanted to discuss is the way of thinking about resources: *You’re free to map different URLs to one controller.* One of main architectural concepts in REST is that it’s up to you how you design your resources and how to expose them.

*Query parameters don’t kill your mother* and choosing named URLs is free – it’s absolutey “RESTful”.

}}}

3 thoughts on “Rails Misapprehensions: Query Parameters are RESTful

  1. URI syntax gives us another option to consolidate search resource: path segment parameters (http://tools.ietf.org/html/rfc2396#section-3.3 ) instead of query parameters.

    So, instead of using URL like “http:///articles/shirts/female?color=red&size=s” where the query terms are related to the shirt but look like to apply to the female resource, you can write: “http:///articles/shirts;color=red;size=s/female” (or can be simplified in “http:///articles/shirts;red;small/female”) which clearly states you’re looking for “red female small shirts” (or perhaps “female in small red shirts”) and not “red shirts for small female” (“http:///articles/shirts;red/female;small”) or “shirts for small red(?) female” (“http:///articles/shirts/female.xml;small;red”… in XML format! you perv’ :-).

    Two small problems with this syntax however: HTML forms do not allow you to specify such parameters from input field directly 😦 and I’m not sure how to tell Rails to extract those parameters from the request URL.

    Like

  2. I’d been wondering how to do use rails3 routes to do what you do in your example of articles/shirts/female (typing that I realize, “articles”, really? but anyway).

    Except… :defaults…. that implies that the URL can still over-ride these defaults in it’s actual query component. Which seems undesirable. articles/shirts/female?gender=male … um, that really shouldn’t be allowed.

    is there any way in rails3 routing to specify those as invariants rather than defaults?

    Like

Leave a comment