zerosum dirt(nap)

evolution through a series of accidents

zerosum dirt(nap)

REST vs AutoComplete

April 18, 2007 by nap · Comments

After struggling with it probably a little bit more than I should have, I’ve totally come around to the REST way of looking at things. It seems clean and nice, and I’m 100% behind it. That said, I’ve found that once you adopt the mentality, things that don’t gel with it start to stick out like the guy in the fur coat at the PETA meeting.

Case in point: the ever-popular Rails auto_complete_field helper. To back up my accusation here, let’s walk through an example scenario with a REST app, and examine the issues that arise…

Imagine a really simple web application which consists of a collection of Articles. The only user interaction is that guests can comment on articles and tag them with keywords. So in a RESTful world, we have an Articles resource, and a Tags resource. Tags are also nested on Articles such that when you ask for /articles/:article_id/tags you’re asking for the subset of tags which have been applied to article_id. We might present these as a tab you can click on when viewing an article resource in a browser.

Now let’s say that there’s a form somewhere (maybe the #new action on an ArticleCommentsController), which can be used to apply new tags to a given article. There’s an auto_complete_field in that form, that will suggest tags to apply to an article, based on the tags that have already been applied. Dumb example, I know, but hear me out.

So, given this scenario, it would make sense to point our auto_complete_field helper at article_tags_path(article_id). This is about as RESTful as it gets — we’ve become a client of our own API. Nice! Our #index action on ArticleTagsController, in a perfect world, would do a couple things above and beyond just displaying the pretty HTML list of tags on the article:

  • It would have a respond_to block. if a browser client is asking for XHTML, we probably want to render a nice paginated view of the relevant tags, ordered by weight, with a nice layout. On the other hand, if we’re asking for XML or JSON, it just returns no-frills data in the appropriate format.
  • it would optionally check for a filter query string. perhaps we set params[:filter] = :attribute_name and then make the actual string filter value (the thing we’re trying to help auto-complete) available via params[:attribute_name]. in the case of our tags example, we’d end up with a params hash that has filter=name and name=zer (or some other text string). If a filter parameter is found, we’d filter the results by the pattern specified. This could all be wrapped up in a nice little helper.

This proposal raises a couple issues. First, the auto_complete_field helper as it exists today expects us to return some HTML from the AJAX call that we can plug into an appropriately named DIV. This is simple and works well, but if we’re really consuming our own web service, we should probably be talking to it via JSON or XML and have a JavaScript handler to process the results, converting them into list format or whatever it is that we desire. But I have to admit that this convenient hack works nicely.

More importantly, if the auto-complete filter is being applied to the collection of resources, that means it maps to the #index action by way of a GET request. So our parameters end up encoded in the URL with a query string like ?filter=name&name=zer. Obviously, GET params are a little more limiting than POST params in terms of length and (perceived) security. But for simple filter strings that take a short sequence of characters, I don’t see this as being an issue. And this is always the case when doing an auto-complete, as far as I can figure.

Note that the auto_complete_field JavaScript helper doesn’t actually allow you to specify an HTTP verb other than POST, although that’s easy enough to change. Surely the core team would accept the one-line fix required to support a :method => :get option if it’s the “right thing to do”. The real problem is more of a philosophical one: are we, as a community, really going to embrace REST 100% or is it acceptable to add small bits of cruftiness in places where it seems inconvenient?

A perfectly legitimate half-way solution is to define a standard #autocomplete action for any resource you want to use in this manner. The advantage to this is that you can easily use a POST against a custom :collection method on the resource. That way, we continue to work inside the existing box of conventions. But I ask you, is that really RESTful?! What do you think?

blog comments powered by Disqus