views:

27

answers:

1

It is very common in Rails for an objects_controller controller to have RESTful edit and destroy actions like so:

def edit
  @object = Object.find(params[:id])
end

def destroy
  @object = Object.find(params[:id])

  @object.destroy
  redirect_to :back
end

With an associated view that provides edit and destroy links like so:

<%= link_to "Edit the Object", edit_object_path(object) %>
<%= link_to "Delete", object, :confirm => 'Are you sure?', :method => :delete %>

And it is easy to blow this up. If I open two browser windows, A and B, destroy an object with the "Delete" link in browser A and then press the "Edit" link in browser B, the find() in the edit action throws an exception.

Updating to add Jakub's suggestion

There are several ways to deal with this:

  1. catch the exception and recover gracefully in the edit action
  2. use @object = find(:first, "conditions... etc. and test the @object in the edit action
  3. use a general 404

But seeing as this is such a common pattern, I would love to know how other folks deal with this situation.

+1  A: 

You edit your 404 page in public/404.html to be something reasonably friendly explaining that what the person is trying to access is not available anymore. That's the general solution. However your domain could allow for example soft-deleting and then you could offer to un-delete the record in the edit view. Checkout the Paranoid plugin for that (I'd implement it quite generally in a before_filter).

Jakub Hampl
Thanks Jakub - this makes sense. The 404 seems like a good approach if the situation is unlikely, but it seems like a bad user experience in an application where very frequent edits could sometimes lead to the exception. I think in those cases one would want to be more specific with the error message back to the user. And thanks for the pointer to paranoid -- I'll check that out.
Greg