Exceptional plugin

Plugin details

Exception Handling Plugin for RoR

Websitehttp://nullstyle.com/home/exceptional Repositoryhttp://hg.nullstyle.com/exceptional/ Author Scott Fleckenstein Tags exception LicenseMIT

Documentation

Install the plugin:
ruby script/plugin install http://hg.nullstyle.com/exceptional/

The handles Directive
=====================
The handles method allows you to specify a method that will handle an exception that is raised within your application and not caught by a normal rescue clause. Below is a sample invocation of the handles directive:

  class SampleController < ApplicationController
    handles AccessDeniedError, :with => :access_denied
  
    def supah_sekret_akshun
      ...
      raise AccessDeniedError
      ...
    end
  
    private
    def access_denied
      render :text => 'no, u kant'
    end
  end



The first argument for the handles directive is either a class or :unhandled. The handler provided by :with is called if the raised exception is a subclass of the class provided, or, if :unhandled is specified, no other handles statement rescue for the raised exceptions.

the handles directive behaves similar to the filter directives such that if multiple directives match the raised exception, all of them will be called.

#both will get called when 'raise "blah"'
handles RuntimeError, :with => :bad_juju
handles RuntimeError, :with => :email_mothership



The following options can be specified for the handles directive:

:with   # (required) The handler to call when the class specified is raised
        # and all of the guard options pass
:when   # (either :public, or :local)  restricts the handler based on whether 
        # the request originated from the server machine (:local) or from
        # another machine (:public).  
:only   # behaves like filters;  if the action that raised the error isn't in
        # the only list, the handler isn't tripped
:except # behaves like filters;  if the action that raised the error is in the
        # except list, the handler isn't tripped



if the handler method takes a parameter the raised exception will be passed.

Here are some examples of what you might use the handles directive for:

  # perhaps you let your users type in what they were doing when the unhandled 
  # exception occured, ala the microsoft crash reporting dialog.
  handles :unhandled, :when => :public, :with => :redirect_to_error_form
  
  #Get A Rich 404
  handles ::ActionController::RoutingError, :with => :render_404
  handles ::ActionController::UnknownAction, :with => :render_404
  handles RecordNotFound, :with => :render_404, :only => :show
  
  #show an invalid request screen when trying to update a non-existent record
  handles RecordNotFound, :with => :invalid_update, :only => [:update]




The raises Directive
=====================

On the opposite side of the handles directive is the raises directive, which provides a exception-based version of the verify directive built into ruby on rails. This directive achieves its work using standard before_filters under the covers, and as such it follows the normal filter semantics.

below is a sample invocation:

  class ProtectedController < ApplicationController
    #an AccessDeniedError will be raised unless the session collection contains
    #the :logged_in key
    raises AccessDeniedError, :unless => {:session => :logged_in}
  
  end



The following options can be specified for the raises directive:

:if     # a hash of options to check, similar to the verify directive.  See 
        # below for further details
:unless # a hash of options to check, similar to the verify directive.  See 
        # below for further details 
:only   # behaves like filters;  won't raise unless the called action is in 
        # the list
:except # behaves like filters;  won't raise if the called action is in 
        # the list



additionally, a block can be passed to the directive that can be used to determine if the error should be raised. Return true to raise the error. The block gets executed within the context of the controller.

The :if and :unless options
---------------------------
the :if and :unless options are hashes that consist of the following key/value pairs:

:params   # a single key or an array of keys that will satisfy the condition if
          # they are all in the params
:session  # a single key or an array of keys that will satisfy the condition if
          # they are all in the session
:flash    # a single key or an array of keys that will satisfy the condition if
          # they are all in the flash
:method   # a single key or an array of keys — any one of which will satisfy the
          # condition if the action is called with that method. (The key should
          # be a symbol: :get or :post, for example.)
:xhr      # true/false option to ensure that the request is coming from an Ajax
          # call or not.



It is not valid to specify a combination of the :if, :unless, or block-based conditions on a single raises statement. If a complex conditional is needed just use a block-based raises directive.

Some example raises directives are below:

  raises InvalidUpdateError, :unless => {:params => :id}, :only => :update
  raises BadJuju, :if => {:flash => :notice}, :only => :new
  
  raises AccessDeniedError :except => [:show, :list] do
    !@account.authorize :write, :update, :destroy
  end



app/errors and the error generator
==================================

With this added exception handling richness to the rails world, it now becomes desirable to start creating app-specific errors within your work. Exceptional gives you the ability to easily generate errors into which you can collect and work with rich, application-specific data. the generator is executed thusly:

script/generate error NAME



such that passing AccessDenied as NAME will generate in app/errors/access_denied_error.rb:

class AccessDeniedError < ApplicationError
end



ApplicationError is generated for you when you install the plugin, so you can group any common error functionality there. Additionally, every exception that derives from Exceptional::Base will automatically be populated with the requests controller from which you can pull information. An example use might be to populate a Request404Error with the request path:

class Request404Error < ApplicationError 
  def request_uri
    controller.request.request_uri
  end
end



An additional note on errors: the controller attribute is populated using the method set_state(controller) in Exceptional::Base. Feel free to override it and provide your own custom logic.

Further Documentation

There is currently no advanced documentation for this plugin.

New documentation

Edit plugin | Back in time (2 older versions) | Last edited by: hardway, about 1 year ago