How I broke it, how I fixed it, and how I learned my lesson
I figured out the problem while lying in bed this morning, and it boils down to "I did something stupid." (Doesn't it always?)
The smart part
First, the smart part: I followed some neat advice about setting up access control and permissions. It gives you some great a great syntax for saying what's allowed, like this:
<%= link_to 'Delete', @photo, :confirm => "Really delete this photo?", :method => :delete if current_user.can_delete?(@photo)%>
(The current_user
bit comes from the Restful-authentication plugin.)
The author also shows how to handle the case where a user tries to type in a URL for which you haven't given them a link. It involves setting up a special exception class, which subclasses StandardError
, and handling it with something like a 401.html
- access denied.
The stupid part
What I did that was stupid was I followed his example blindly. He shows this:
def rescue_action(e)
case e
when SecurityTransgression
head :forbidden
end
end
...which handles the SecurityTransgression
fine, but breaks the default error handling in Rails. (I'm sure the author knows this and dealt with it, but he didn't discuss it.)
The solution
The solution was to add two lines:
def rescue_action(e)
case e
when SecurityTransgression
head :forbidden
else
super
end
end
The "else super" part says "if I haven't specified anything here, hand the error back to StandardError
, so it can do its normal stack trace stuff."
Now I'm getting the correct stack trace for my original problem, and will proceed to troubleshoot it.
The lesson: be careful when you mess with exception handling, and make sure the default case still works!