views:

91

answers:

4

After destroying a resource in my Rails application, the user can restore it clicking on a link.

Currently this restore action is routed to the destroy method of the corresponding resource controller.

When this method finds the resource in the database, it destroys it and moves the record in a trash table.

When it does not find the resource in the database, it searches for it in the trash table and if it finds the resource it restores it.

I am not very satisfied by this way of doing, with the destroy method having two purposes: destroy and restore.

I could create a dedicated restore action in my controller, but in a REST way, where would you place the restore request handling? In a dedicated controller? If so, with which method, PUT or POST?

A: 

I think that since the action is on a resource, the functionality should live in the ResourceController. One of my working understadings of a RESTFUL architecture is that a rule of thumb on deciding between PUT and POST is that POST is used for creates and PUT is used for updates. In this case, I would expect that the resource 'exists' and you are updating it's state that your would use a PUT and the restore URI would be something like:

http://example.com/resources/restore/{id}

Sean
+1  A: 

I think a REST purist would create a new resource called Trash which is handled by a TrashController. To handle a restore, you would have an action on TrashController called Restore.

The URL would look like this:

http://example.com/trash/restore/{resourceId}
DSO
how would you go about making this polymorphic so that you could us the use the same controller to restore multiple different objects accross your application?
ErsatzRyan
DSO
A: 

I think Sean above was on the right track but I would take it a step further. Make the trash action a POST that updates the resource with trash=1. Then restore is just another POST to the same resource with trash=0

EDIT: Replaced incorrect method PUT with POST given the request is not sending the entire resource, just an update of a part of the resource.

rojoca
+1  A: 

POST is non-idempotent, meaning if you send the same POST request many times, you will get many new items. PUT should be idempotent, since the same update happening on the same resource should have no side effects when executed multiple times.

As for where this action should go, it really depends on your aesthetic sensibilty and how hardcore you want to be about REST versus keeping your Rails controllers clean and well organized.

It's certainly arguable that a DeletedBob is different resource from a Bob. You could say that a PUT sent to the DeletedBobsController would update the DeletedBob resource, perhaps with a parameter like "deleted=false" to indicate the purpose of the update.

You could also consider Deletions as a resource. Then you could use DELETE on the DeletionsController with the params "resource_type=bob&resource_id=23". By destroying the deletion, you are restoring the original object. Subsequent identical calls will yield an "object not found" error, as one would expect with DELETE.

Personally, ever since Roy Fielding (original author of the dissertation defining REST) came out and said there's really nothing wrong with POST, I would consider defining an additional :put => :restore method and route on my BobsController. It keeps the code where another programmer would expect it, and they are likely the only audience for this kind of design.

austinfromboston