In a brand new Rails application with a scaffolded RESTful model, the generated delete code looks like this:
class BeersController < ApplicationController
# DELETE /beers/1
# DELETE /beers/1.xml
def destroy
@beer = Beer.find(params[:id])
@beer.destroy
respond_to do |format|
format.html { redirect_to(beers_url) }
format.xml { head :ok }
end
end
end
If a user tries to delete the same Beer twice (maybe a quick double-click, or actions in two different browser tabs) they will get a RecordNotFound error resulting in a 404 page. This is a pretty unfriendly experience; it seems like it would be better to complete the redirect back to beers_url
regardless, possibly with a flash
error, since there isn't really anything the user can do about the second delete failing.
An alternative approach is to act like the delete succeeded anyway with something like this:
def destroy
@beer = Beer.find_by_id(params[:id])
destroyed = @beer.try(:destroy)
respond_to do |format|
format.html { redirect_to(beers_url) }
format.xml { destroyed ? head(:ok) : head(:not_found) }
end
end
I can understand the desire for a hard 404 error in the API use-case, but it's harder for me to justify for a web application. Can anyone provide a good reason why we should throw a scary error at the user in the name of RESTfulness?
(This question isn't particular to Rails, but I don't know how other frameworks handle this case out of the box).
UPDATE: It turns out I was wrong: https://stackoverflow.com/a/24713946/14731
Previous answer:
HTTP DELETE
is an idempotent operation. Invoking it multiple times consecutively must result in the same behavior as the first. Meaning: you shouldn't return HTTP 404.