Since Merb has the lovely property of rendering the output of an
action, using ruby-level exceptions to render error pages in Merb
could be a cute way to approach error handling.

Suppose one has an action for editing a product which you would like
to restrict to administrators:

  def edit
    raise AdminAccessReqired unless session[:user] and session[:user].admin?
    @product = Product.find(params[:id])
    raise UnknownProduct if @product.nil?
    render
  end

Where AdminAccessReqired and UnknownProduct are ControllerExceptions.

The controller exception hierarchy would be rooted with the base
class, Merb::ControllerException. The Merb dispatcher would rescue any
exception which was a kind_of ControllerException. Derived from
ControllerException would be an exception for each of the HTTP error
codes. For example:

  module ControllerExceptions

    class Unauthorized < ControllerException
      STATUS_CODE = 401
      # ...

    class Forbidden < ControllerException
      STATUS_CODE = 403
      # ...

    class NotFound < ControllerException
      STATUS_CODE = 404
      # ...

Application authors could place addition derivations into
dist/app/exceptions. These must be children of an already defined Merb
controller exception class. The user defined exceptions would have a
method called 'action' which acts like typical controller action. It
is called to render a page when the exception is raised. For example

  # dist/app/exceptions/admin_access_required.rb
  class AdminAccessRequired < Merb::ControllerExceptions::Unauthorized
    def action
      if session[:user].nil?
        redirect '/login'
      else
        render # views/exceptions/admin_access_required.rhtml
      end
    end
  end

If the user is logged in but does not have administrative access, this
will render a page describing the problem with the proper HTTP status
code 401.

The UnknownProduct exception might look like this:

  # dist/app/exceptions/unknown_product.rb
  class UnknownProduct < Merb::ControllerExceptions::NotFound
    def action
      @id = params[:id]
      render # views/exceptions/unknown_product.rhtml
    end
  end

If passed a bad id, the server will respond with 404 and a page that
is specific to missing a product.

The advantages of this scheme are
- Simplifies controller action definitions by placing exceptional
logic elsewhere
- Eases the conformity to HTTP by returning proper error codes
- Could allow for before and after filters around a restricted type of
exceptions (eg, for logging purposes)
- Further modularizes testing code: one needs only to check that an
action raise a particular exception

Thoughts?
I would gladly implement this and submit a patch if the list thinks
this that it is a worth feature.

The idea is from Robert Hahn:
http://blog.roberthahn.ca/articles/2007/06/22/setting-http-response-codes-with-exceptions



ry
_______________________________________________
Merb-devel mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/merb-devel

Reply via email to