Topic: Raising Custom Exceptions

It seems to me that a suitably-DRY way of handling (some)errors would be raising custom exceptions, which you could then handle in rescue_action in your controllers.

For example, in a user authentication controller:

def AccountController < Application Controller
  def rescue_action(e)
     case e
     when BadPasswordException
       render :action=>"error_template"
     end
  end

  def login
    # Blah Blah Blah
    if # Password doesn't match
      raise BadPasswordException
    end
  end
end


Perhaps not the best example - it is a more obvious point where the exception might be raised in several points in a controller.

Anyway, is this a good idea? And if so, where is the best place to define the exception objects?

Cheers

Jason

Re: Raising Custom Exceptions

aesthete80 wrote:

Anyway, is this a good idea?

I think it's a good thing to do in some circumstances, but I wouldn't overdo it by creating dozens of these and trying to juggle them all in the rescue_action clause. Instead I recommend revealing this through refactoring. In other words, only do this once you see the duplication.

aesthete80 wrote:

And if so, where is the best place to define the exception objects?

Good question. I'm not sure the best practice for this. You'll probably want to put it in the ActionController module because that's where Rails defines all of its other custom exceptions related to the controller.

module ActionController #:nodoc:
  class BadPasswordException < ActionControllerError
  end
end

But as far as where to put this code, maybe in a custom file in the lib directory? Or maybe at the top of application.rb. I'm not really sure.

Railscasts - Free Ruby on Rails Screencasts

Re: Raising Custom Exceptions

Ah, thanks for that Ryan. I've had a bit of a play, and come up with the following which works:

In lib/exceptions.rb

module Exceptions
  class BadPasswordException < StandardError
  end
end

and then simply include it in application.rb so it's available to all your controllers

class ApplicationController < ActionController::Base
  ...
  include Exceptions
  ...
end

I'm doing this as part of a refactoring - In my actual application, I was getting a lot of duplicated error code based on object/action-based permissions, so that's why I wanted to wrap all the error handling code (display a nice error message, log the exception etc) in one place.

Cheers

Jason