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