Home
ryah [entries|archive|friends|userinfo]
ryah

[ website | tiny clouds ]
[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

Merb 0.4 [Nov. 8th, 2007|12:36 am]
[Tags|]

Merb 0.4 was released today with a new website. My controller exceptions thing is mentioned in the feature list.
LinkLeave a comment

A Proposal To Magically Remove 'params' [Sep. 2nd, 2007|01:19 pm]
[Tags|, ]

I have a magical proposal for the anti-magic web framework.

Controller methods do not use arguments and yet expect arguments. This is handled through this params hash because we don't know in advance what parameters a client could pass to Merb. But in almost every instance, it is too much to know all the query parameters - one doesn't care if the user threw in an extraneous variable - one only cares about the variables we need to process the action.

Instead of using params we could make actions more functional by taking advantage of this cool programming concept called arguments. An example
  class ProductController
    def show(id)  # GET /products/show?id=12
      @product = Product.find(id)
      render
    end

    def index(page = 1)  # GET /products?page=2
      @products = Product.paginate_all(page)
      render
    end
  end
Getting a parameter list for a method is rather difficult, but using [info]zenspider's ParseTree it is possible. Proof of concept.

ParseTree is slow, but it only needs to be run once at load - we can cache the argument lists for each method.

It is extremely magical, but the magic is limited in scope - we are not going to be using this all around the the source tree. Only for controller actions.

It does not increase the frame stack and should have zero effect on performance.

Advantages:
  • Less to type. No more params[:username], just username
  • Cleaner API. At a glance it is visible what parameters actions take.
  • params in its current state is slightly dangerous. Clients can pass to it whatever (key, value) pairs they want and Merb will blindly symbolizes the keys. These symbols are never garbage collected.
  • We can automatically raise a BadRequest if the user does not supply all of the arguments needed.


x-posted
Link14 comments|Leave a comment

merb cookie storage sessions [Aug. 31st, 2007|02:33 pm]
[Tags|, ]

cookie storage session port to merb

will add AES encryption option soon
LinkLeave a comment

Controller Exceptions in Merb [Jul. 31st, 2007|07:59 pm]
[Tags|, ]

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/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
The idea is from Robert Hahn

x-posted here
LinkLeave a comment

navigation
[ viewing | most recent entries ]

Advertisement