Where do you REST your head?

Sure, it's nearly effortless to add a new XML-based API to your
application using the latest stuff in Rails Edge, but what do you do
when the Sandman comes? (Sorry about all the puns!)

Lately, I've been very interested in the stuff coming out in Rails
Edge and eventually 1.2, emphasizing the CRUD design technique and
using REST based services. A lot of this has been spurred on by DHH's
keynote at RailsConf that I watched via the web.

The technique is liberating! All your controllers do basically the
same things, which are the major CRUD operations (index/show, create,
update, destroy) and the typical special representations (edit, new).
However, when it comes down to the nitty gritty, there are a few
concerns I still have.

Just to test my understanding of the domain and technique, I set
out prototyping a new application this morning. It's based on an old
PHP app we have that is used to manage the supplemental online
databases that KCKCC Library owns or subscribes to. The basic format
is very simple: Databases belong to a Category and each have
several simple fields, with a few validations.

I started with the CategoriesController to see if I
could figure everything out. I created the seven basic actions and
added the default respond_to blocks. Here's a simple
example:

That one was pretty straightforward. What became a brain-twister
were the methods that actually modified something. Ideally, in an XML
API you don't have to print out a big response when a record was
created, deleted or updated. The way you do that is with status
codes, and it is something that showed up in DHH's talk. Here's how I
would do the create action:

Simple, right? You just send back the location of the new record
in the header, and return a 201 status code (Created). This is all
well and good until you have some misbehaving clients. What if the
new record wasn't created because it failed validation? With our HTML
templates, we might do this:

But what should we do with the XML API? We need to refer to the
HTTP 1.1 status codes, of course, specifically the 4xx ones, which
refer to errors on the client-side. Here are our options
(from here):

400 Bad Request

This is primarily for malformed requests. Personally, I think
this is inappropriate because it doesn't say that the record
submitted failed validations, but that it had bad syntax -- not
exactly the same thing.

406 Not Acceptable

At first, I thought this would be it, but actually it refers
specifically to the Accept: header and that the resource cannot be
returned in an acceptable format.

409 Conflict

Finally, a good candidate! Quoth W3C, "The request could not be
completed due to a conflict with the current state of the
resource. This code is only allowed in situations where it is
expected that the user might be able to resolve the conflict and
resubmit the request." They go on to talk about potential uses for
versioned resources, etc. Most importantly, however, they mention
that the response should give adequate information about how to
resolve the conflict.

412 Precondition failed, 417 Expectation failed

These both looked good at first, but of course they refer to
specific HTTP headers just like 406 does. Sorry, boys, you're
out.

So in the end, I decided 409 was the best for
the create action. Now, we need to provide information
about "how to resolve the conflict". Why not return the errors that
were added to the object?