| ryah ( @ 2007-07-31 19:59:00 |
| Entry tags: | merb, projects |
Controller Exceptions in Merb
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
endWhere 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
endIf 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
endIf 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/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
x-posted here