RESTfulness in Pylons
---------------------

I've been trying to buld a web application in a RESTful fashion, using
for guidance among other resources the Leonard Richardson and Sam Ruby
book _RESTful Web Services_. I've learned that REST is a style of
architecting applications, and that Pylons with the map.resource()
function of routes can be seen as one particular way of defining and
working within some RESTful constraints.

The way that map.resource() sets things up is basically as follows.
There are two types of URL, collections (/resources) and individuals (/
resources/6), and four HTTP verbs, GET, POST, PUT, and DELETE. These
are variously combined to allow for seven different REST actions:
index, show, new, edit, create, update, and delete.

If you group the REST actions by type of URL, you get the actions that
work on collections: index, new, create
and the actions that work on individuals: show, edit, update, delete

To make a RESTful web application under these conditions means to
express all functionality the application provides in terms of
resources and those seven actions acting on resources. This is an
interesting and challenging project, and to the extent that it can be
successful, the benefits of the RESTful approach are significant. Now,
on to my current problem!

Batch Operations
----------------

How do you implement batch operations on collections of resources?

Imagine you have a resource Messages. If you "GET /messages" it
returns an index of messages.
If you "DELETE /messages/4" it will delete message 4.

Perhaps the "GET /messages" index includes for each resource in the
collection a form with a button that allows the client to send an HTTP
DELETE to that message's URL. So if there are ten messages in the URL,
there will be ten items returned by the index action, and those will
include ten forms, one to send a DELETE to each of the ten messages.

Now, suppose you wish to have a way for the user to do a batch delete
on a subset of messages. The traditional (non-RESTful) way to achieve
this is to have the list of ten messages inside a single form, with a
checkbox for each list item. The Delete button would submit an
overloaded POST to some URL such as "POST /messages/delete" and the
server can delete all the checked off items. Or, alternatively, there
will be an even more generic URL, "/messages/batch" and the fact that
the selected messages are to be deleted or moved to a different folder
will be specified as an input element of the form. But of course
neither of these is available in the current RESTful framework. The
way to delete a set of five different messages is to send five HTTP
requests, each of the form "DELETE /messages/:id".

Is it possible to allow batch operations within the RESTful
constraints? If so, what is the best way to do this?

Three Ideas
-----------

1. Use AJAX techniques to submit the five requests for the user.
Basically have the form submit intercepted by a javascript which fires
off five asynchronous HTTP DELETE requests to the five URLS and
collects the responses for display. This requires no changes to the
server API. If the client does not have javascript, the interface can
degrade gracefully to requiring a separate submit button click for
each delete.

2. Of the seven REST actions, four of them (show, edit, update,
delete) act upon individual resources. Extend these to be able to act
on collections of resources, and therefore also generalize the URL
formats to allow for addressing subsets of collections. For example,
the URL "/messages/3,4,18,22-50" refers to a subset of the collection
of messages. An HTTP DELETE to that URL would delete each resource in
that subset.

In this case, of the remaining 3 REST actions that act only upon
collections, index, new, and create, one of them, index, would be
updated to act on proper subsets of the collections, and the other two
would behave the same whether the URL refers to the entire collection
or some subset.

One big challenge of this approach is creating a scheme for addressing
arbitrary subsets of a collection, and by addressing I mean having it
in the URL. The scheme would have to be such that the URLs could be
created using HTML forms. Finally, after developing the scheme it
would also require significant changes to routes to support it.

3. Use overloaded POST to create new REST actions in addition to the
basic seven that are meant to support batch operations. For example,
three new actions called batch_create, batch_update, batch_delete. In
this case it is not necessary to address subsets in the URL; the
collection URL for a resource can be used instead. However support in
routes map.resource might be required to route the incoming POST to
the proper RestController action. The POST request body for each of
those actions can contain the set of resources and representations to
act upon.

One difficulty here is figuring out the best way to modify the route
configuration to identify the three new actions. Currently, the only
trickery routes explicitly supports for RESTful apps is the _method
input element used to translate POST to PUT or DELETE, which makes up
for a deficiency in modern browsers and/or HTML 4 that makes it
impossible for most clients to construct an actual HTTP PUT request.
But the current problem doesn't need to translate one HTTP method to
another HTTP method, it needs to include additional information to
distinguish between multiple actions at the collection level. Perhaps
it can be done on the model of the new action, for which the url is '/
messages/new'. So in this case we can have '/messages/batch_create', '/
messages/batch_update', etc.

I'm currently leaning toward option 3. One downside is that a strength
of the RESTful approach is the simple server API. Option 3 does
increase the breadth of the server API, but on the other hand it isn't
obvious that it does this in a way that is inconsistent with REST
principles.

So, has anyone tried to tackle this problem before, of batch
operations in the RESTful framework? Did you try anything like the
approaches I've described above? Any stories of success, pitfalls to
beware, known theoretical limits or false assumptions I've made, or
general engineering advice?

Thanks

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"pylons-discuss" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/pylons-discuss?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to