views:

1277

answers:

3
new_story GET     /story/new(.:format)  {:action=>"new", :controller=>"stories"}
edit_story GET     /story/edit(.:format) {:action=>"edit", :controller=>"stories"}
     story GET     /story(.:format)      {:action=>"show", :controller=>"stories"}
           PUT     /story(.:format)      {:action=>"update", :controller=>"stories"}
           DELETE  /story(.:format)      {:action=>"destroy", :controller=>"stories"}
           POST    /story(.:format)      {:action=>"create", :controller=>"stories"}

In web work I have done with other technologies I only ever used GET and POST methods. But with RESTful routes in Rails, by default the PUT and DELETE methods are used for the update and destroy actions. What's the advantage or need for using PUT and DELETE? I assume these methods are just another way of doing POST - but why not just stick with POST?

+10  A: 

The advantage is mostly semantic, and can also simplify URLs to an extent. The different HTTP methods map to different actions:

POST   => create a new object
DELETE => delete an object
PUT    => modify an object
GET    => view an object

Then, in theory, you can use the same URL, but interact with it using different methods; the method used to access the resource defines the actual type of operation.

In practice, though, most browsers only support HTTP GET and POST. Rails uses some "trickery" in HTML forms to act as though a PUT or DELETE request was sent, even though Rails is still using GET or POST for these methods. (This explains why you might not have used DELETE or PUT on other platforms.)

mipadi
Good explanation. Without getting into too much detail, what kind of "trickery" are we talking about?
It's pretty simple, actually. When using Rails' methods for generating forms, if you specify PUT or DELETE, Rails will actually POST the form, but it includes a hidden field in the form that specifies the desired HTTP method. Then, when processing the form, Rails looks for that hidden field, and if it exists, it reports (through the request object) that the form was sent using DELETE or PUT, even though it was really sent using POST. So basically, if you specify DELETE, request.method returns :delete, even though the form was POSTed. This all happens automagically.
mipadi
That is simple. Thanks.
+3  A: 

That'd be kind of like asking why "delete" a file when you could just set its contents to zero bytes and the file system would just treat that as a delete. HTTP has supported verbs other than GET/POST forever but the way SOAP evolved kinda twisted the original meaning of those verbs. REST is a simpler, back to basics approach that uses the verbs as they were intended instead of inventing some new verb concept inside of the payload.

Josh Einstein
A: 

Here's the "methods" section of the HTTP 1.1 spec; it defines lots of methods, and they all have different benefits and tradeoffs. POST is the most flexible, but the tradeoffs are numerous: it's not cacheable (so the rest of the internet can't help you scale), it isn't safe or idempotent so the client can't just resend it gets an error, and it is no longer clear exactly what you're trying to accomplish (because it's so flexible). I'm sure there are others but that ought to be sufficient. Given all that, if the HTTP spec defines a method that does exactly what you want your request to do, there's no reason to send a POST instead.

The reason POST is so common is that, historically at least, web browsers only supported GET and POST. Since GET is defined to be safe and idempotent (even though many applications don't adhere to that), the only safe way to modify data was to send a POST. With the rise of AJAX and non-browser clients, that is no longer true.

BTW, the mapping @mipadi gave is the standard mapping, but it isn't the only valid one. Amazon S3, for instance, uses PUT to create resources. The only reason to use POST is if the client doesn't have sufficient knowledge to create the resource, e.g., you back your resources with a relational database and use artificial surrogate keys.

Hank Gay
Thanks. Didn't know about idempotent. Interesting feature. Can't think what you would use it for though.
Retry in the face of failure; if you don't get an `ack` you can just send it again - it's guaranteed to be no different than if the first had worked.
Hank Gay