Preparing for Rails 2.0: Controller-based exception handling

Share this article

Since Ruby is a pure Object-Oriented Language, exceptions play a big role in the flow of control. Previously, you had the choice of rescuing exceptions at a local level or you could override the rescue_action method in your controller.

The former method gave you really fine-grained control of what to do in the case of an exception:


begin
    user.save!
rescue ActiveRecord::RecordInvalid
    render :action => 'new'
end

In this case, if the ActiveRecord::RecordInvalid exception is raised (the save! method will raise this if validation fails) Rails will render the ‘new’ action. It became clear, though that adding begin/rescues around the same methods is pretty time consuming and not very DRY – which is where the rescue_action became helpful:

def rescue_action(exception)
  if exception == ActionView::TemplateError
    render :template => 'errors/404'
  else
    super
  end
end

This (rather contrived) example will trap any ActionView::TemplateError and render the 404.erb file in the /app/views/errors directory. You are able to drop that method into any controller (including app_controller), but again, there is a lot of work involved in setting them up, making sure each controller performs the correct action for a given exception, which is why Rails 2.0 introduces rescue_from.

rescue_from is an attribute of each controller, and allows you to define a method to run when a particular exception is called. So the above example would become:


rescue_from ActionView::TemplateError, :with => :render_404

def render_404(exception)
   render :template => 'errors/404'
end


or if you prefer to use a inline block:


rescue_from ActionView::TemplateError do { render :template => 'errors/404' }

In the current PR release, the rescue_from technique can only catch exceptions of an exact type, so it wouldn’t catch sub-classed exceptions – if you had a custom exception called MyTemplateError that extends ActionView::TemplateError the above code won’t work. The good news is a patch to edge rails fixes this issue, so the release version of Rails 2.0 will work as expected.

Myles EftosMyles Eftos
View Author

Myles a Perth-based web developer who has worked in all the major web languages, his weapon of choice being Ruby on Rails—although he’s found himself doing more and more front-end development in JavaScript, HTML, and CSS.

Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week