“Making Rails Better – Error Handling”
January 5, 2008
Error handling in web applications is devilishly complex – we ended up rewriting SIAS’s error handling code in almost every release.
There are two main sources of complexity. First, how do you handle
errors that occur after you’ve already started returning a response to
the client? The easiest solution, and the one Rails adopts, is to cache
the generated result until its complete. If an exception occurs you
dump the result and then render an error message – making damn sure
your error message generating code is beyond flawless. This works if
your results tend to be small, but breaks down if you need to return a
lot of data to the client. For this article, let’s stick with Rails
assumption (we couldn’t use it for SIAS).
The second issue is how do you return errors to the client – what
format and HTTP status codes should you return? Unfortunately, most
standards are mum on this point. For example, nowhere in the Atom
Publishing Format does it tell you what to do when an error occurs. On
the other extreme, the Web Map Server (WMS) standard, which we
supported in SIAS, goes overboard. Since a Web Map Server is supposed
to return a map, usually in a raster format such as PNG or JPEG, the
standard specifies that errors should be returned as bitmaps that
contain the error message (bet you never thought of that!). It also
requires that you support returning errors as “blank” images (so as not
to block out any other maps) and then, for a fun twist, as XML
documents.
Its on this second point that Rails is lacking – error messages are
always returned in HTML and are mapped to two HTTP status codes – 404
(not found) and 500 (internal server error).
An Error Handling Plugin
We can do better. Building off the content negotiation plugin Charlie talked about last week, we have created an error handling plugin for MapBuzz called render_exceptions.
The plugin does four things:
- Adds an :exception parameter to render, so you can write this code:
rescue => e render(:exception => e)end
- Adds a method, http_status_code, to the various Rails exceptions. For example:
module ActiveRecord class RecordNotFound def http_status_code 404 end endend
Note that ActionController::RecordInvalid is mapped to 418, as described earlier on Charlie’s blog and rest-discuss.
- Overrides rescue_action_locally and rescue_action_in_public to use render(:exception)
- Defines a number of error handling templates – such as error_404.rhtml, error_404.rjson, error_404.ratom, error_406.rhtml, etc.
When an exception is raised, the plugin checks to see if the
exception object responds to http_status_code. If it does, and if the
value is not 500, then the plugin picks one of the error templates
using the content negotiation plugin Charlie blogged about last week. Otherwise, the plugin reverts back to the default Rails error handling.
The end result is that errors are returned using the appropriate
mime type and http status code. So if a client asks for an Atom feed of
a non-existent record, the server returns 404 and an error message as
an Atom entry. Similiarly, if the client asks for an HTML document for
a non-existent record, the server returns 404 and an HTML error message.
Using the Plugin
To install the plugin:
- Install the content negotiation plugin.
- Install the render_exception plugin.
- Copy the error templates directory to your views directory (edge
Rails introduces a view search path, but I’m assuming you are using
Rails 1.2.x). Thus you’ll end up with a directory app/views/errors that
contains a number of error handling templates. - Modify the error templates to suite your needs. Most are fairly
generic, so can be used as-is, but others will require some changes - Don’t forget that the plugin overrides rescue_action_in_public, so
make sure that its fits into your global error handling scheme.
And that should do the trick.
Powered by ScribeFire.
Entry Filed under: error handling, rails. .
1 Comment Add your own
Leave a Comment
Some HTML allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <pre> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>
Trackback this post | Subscribe to the comments via RSS Feed
1.
cwxwwwxdfvwwxwx | December 25, 2008 at 11:27 pm
well, hi admin adn people nice forum indeed. how’s life? hope it’s introduce branch