Friday, July 10, 2009

Handling Exception at the Application Level in Rails

At last the point of the project, I found one more important thing that is quite useful and it could reduce the code 20%. That's when I did a handling service error on both server and client. I find myself have been repeating the code on the way. Luckily, after discussion with my colleague, I came up with idea to handle in application controller. It means that instead of handle exception on all of my controllers, I could just handle in a single place whenever exception has raised from these controllers.
Basically, there are two methods (rescue_action and rescue_action_in_public) that you would need to override based on your needs. By default, these two methods do the best job to handle exception both in development and production mode. rescue_action method will be called with an exception parameter that raises inside an action method. rescue_action_in_public method, however, is used for public exception handling (for requests answering false to local_request?). local_request? method tells which rescue_*** method to call.

More importantly, we can handle exceptions for specific controller instead of the whole. All you need to do is to override one of these methods inside that controller.

class PostsController < ApplicationController
   def rescue_action_in_public(exception)
         when ActiveRecord::RecordNotFound then render :file => '/bad_record'
         when NoMethodError then render :file => '/no_method'
         else render :file => '/error'

We can even handle them in a much cleaner way rather than if/else statement by using rescue_from. What it does is that it maps an exception type to handler method. This handler method can take either an exception parameter or a non-argument. We can even specify a proc or block.

class PostsController < ApplicationController

   # Declare exception to handler methods
   rescue_from ActiveRecord::RecordNotFound, :with => :bad_record
   rescue_from NoMethodError, :with => :show_error

   def bad_record; render :file => '/bad_record'; end
   def show_error(exception); render :text => exception.message; end


1 comment:

Anonymous said...

Generally I do not post on blogs, but I would love to mention that this post extremely forced me to try and do therefore! really nice post. thanks, here's a similar subject you'll like [url=]Collectables[/url]

Subscribe in a Reader