Semergence

Seth Ladd’s blog about Ruby on Rails and crunching data.

jvoorhis | What’s New in Edge Rails: Restful Routes

with 6 comments

Restful Routes talks about the new RESTful programming models that are now possible in Rails (now in Edge, soon to be in the released version).

In this case, the url /comments/1;approve would be created. The rationale is to use the path to the left of the semicolon for a resource’s identity, and to use the path to the right of the semicolon as a modifier. Frequently this modifier would be an operation that you would perform on the resource, such as approving a comment that requires moderation.

This isn’t very restful. This modifier hack is just another way to force another verb into the mix.

The best way to be more RESTful would be to PUT a representation of the comment with the approval flag set to true. In REST, representations of resources are exchanged. Instead of referencing the URI of the comment, with a verb modifier stuck on the end, send along a representation of the whole comment.

Now, you’re saying, “But how do I do that in Rails?” This is, of course, very difficult. Most of the fault lies with the XHTML spec, which has been updated to support full method selection in form actions, or the inability to send form data as XML. You don’t really care about the representation format, so the current name=value pairs would work OK as the body of the PUT. But a lack of PUT as a form action? It’s a RESTful crime.

Another way to be more RESTful would be to create a new resource, a collection that accepts ApproveComment documents. This is a document style web service, but minus the SOAP. This models the event that is “Approve this Comment”. You can then POST this new even to the /comments/approval_queue. The representation would include the comment id you want to approve.

This intermediary resource is similar to why Rails has introduced :has_many :through. Those old many to many join tables are old and busted, and first class join models are the new hotness. They function to enrich the domain model and make relationships themselves a first class citizen. I think of these new documents, the ApproveComment document, as filling in the same type of gap.

The URI, /comments/1;approve, both identifies the noun and the verb. To me, that violates a central tenent of REST, in that you should only need the CRUD methods. I see no difference between /comments/approve/1 and /comments/1;approve when talking about the intended consequences of the user’s request.

It’s great to see Rails try to be more RESTful, don’t get me wrong. They are doing some great work here. I’d like to see them take it even farther, and use only the HTTP verbs (GET, POST, PUT, DELETE) and make new documents (representations) for what would have been that URI modifier.

Written by sethladd

July 31, 2006 at 2:35 pm

Posted in rest, rubyonrails

6 Responses to 'jvoorhis | What’s New in Edge Rails: Restful Routes'

Subscribe to comments with RSS or TrackBack to 'jvoorhis | What’s New in Edge Rails: Restful Routes'.

  1. Another approach would be rather than PUT(ting) a representation of the whole Comment with Approved set to true… why not do this:

    HTTP/1.1 PUT /Comments/1/Approved

    TRUE

    This is restful, because you aren’t calling a verb you are setting a property via a PUT. The nice thing is you only need to know the property you want to set not the whole Comment (and all the other properties).

    What do you think? It is a subtle but VERY important distinction.

    Alex James

    31 Jul 06 at 7:24 pm

  2. I don’t think that’s really following the spirit of REST. The URI is an identifier for some resource. What is the resource identified by /comments/1/approved? Can I GET it?

    And how do you disapprove a comment? Is that a DELETE /comments/1/approved ? What if it was never approved? Can you DELETE that resource if it was never approved?

    Also, how do you set lots of properties at once?

    sethladd

    31 Jul 06 at 11:08 pm

  3. Yes you COULD get it if the server supported it, which is of course what I am suggesting. After all a property, or attribute is a resource, it just happens to often be grouped with other resources in a record. Which is how you USUALLY get it. But there is NO rule that stops you from getting that property without retrieving the whole record.

    You disapprove it by PUT(ting) false. Of course this assumes the server is capable of handling this, but the point is you can go lower level than a record to the property and you still have a resource, which you can act restfully on, so long as your server supports it.

    I don’t see what bearing your question “Can you DELETE that resource if it was never approved” has?

    IF you DELETE /comments/1/approved you are attempting to removing a property or attribute (belonging to /comments/1)… depending on how /comments/1 is actually stored that may (RDF triple) or may not (Column in a table) be possible.

    If you want to set lots of properties at once you GET from /comments/1 url of course.

    Does that make it seem more RESTFUL?

    Alex James

    31 Jul 06 at 11:58 pm

  4. The resource identified by “/comments/1/approved” would be the “approved” property of the “/comments/1″ resource. To disapprove a comment, PUT “FALSE” instead. DELETE would unset the property, GET would return “TRUE” or “FALSE”.

    Steve Dunham

    1 Aug 06 at 5:59 am

  5. “Rewriting O/RM’s unwritten rules” is a post what your post prompted me to write, it’s here: http://www.base4.net/blog.aspx?ID=76

    Alex James

    1 Aug 06 at 3:57 pm

  6. Alex dropped the RDF bomb at http://www.base4.net/blog.aspx?ID=76

    Mad props!

    sethladd

    1 Aug 06 at 4:01 pm

Leave a Reply