module Lev::Handler

Common methods for all handlers. Handlers are extensions of Routines and are responsible for taking input data from a form or other widget and doing something with it. See Lev::Routine for more information.

All handlers must:

2) call "lev_handler"
3) implement the 'handle' method which takes no arguments and does the
   work the handler is charged with
4) implement the 'authorized?' method which returns true iff the
   caller is authorized to do what the handler is charged with

Handlers may:

1) implement the 'setup' method which runs before 'authorized?' and 'handle'.
   This method can do anything, and will likely include setting up some
   instance objects based on the params.
2) Call the class method "paramify" to declare, cast, and validate parts of
   the params hash. The first argument to paramify is the key in params
   which points to a hash of params to be paramified.  If this first argument
   is unspecified (or specified as `:paramify`, a reserved symbol), the entire
   params hash will be paramified.  The block passed to paramify looks just
   like the guts of an ActiveAttr model.

   When the incoming params includes :search => {:type, :terms, :num_results}
   the Handler class would look like:

   class MyHandler
     lev_handler

     paramify :search do
       attribute :search_type, type: String
       validates :search_type, presence: true,
                               inclusion: { in: %w(Name Username Any),
                                            message: "is not valid" }

       attribute :search_terms, type: String
       validates :search_terms, presence: true

       attribute :num_results, type: Integer
       validates :num_results, numericality: { only_integer: true,
                                         greater_than_or_equal_to: 0 }
     end

     def handle
       # By this time, if there were any errors the handler would have
       # already populated the errors object and returned.
       #
       # Paramify makes a 'search_params' attribute available through
       # which you can access the paramified params, e.g.
       x = search_params.num_results
       ...
     end
   end

Note that if you want to use a “Boolean” type, you need to type it with a lowercase (type: boolean).

All handler instance methods have the following available to them:

1) 'params' --  the params from the input
2) 'caller' --  the user submitting the input
3) 'errors' --  an object in which to store errors
4) 'results' -- a hash in which to store results for return to calling code
5) 'request' -- the HTTP request
6) 'options' -- a hash containing the options passed in, useful for other
                nonstandard data.

These methods are available iff these data were supplied in the call to the handler (not all handlers need all of this). However, note that the Lev::HandleWith module supplies an easy way to call Handlers from controllers – when this way is used, all of the methods above are available.

Handler ‘handle’ methods don’t return anything; they just set values in the errors and results objects. The documentation for each handler should explain what the results will be and any nonstandard data required to be passed in in the options.

In addition to the class- and instance-level “call” methods provided by Lev::Routine, Handlers have a class-level “handle” method (an alias of the class-level “call” method). The convention for handlers is that the call methods take a hash of options/inputs. The instance-level handle method doesn’t take any arguments since the arguments have been stored as instance variables by the time the instance-level handle method is called.

Example:

class MyHandler
  lev_handler
protected
  def authorized?
    # return true iff exec is allowed to be called, e.g. might
    # check the caller against the params
  def handle
    # do the work, add errors to errors object and results to the results hash as needed
  end
end

Attributes

auth_error_details[RW]

Provided for development / debugging purposes – gives a way to pass information in a raised security transgression when authorized? is false

caller[RW]
options[RW]
params[RW]
request[RW]

Public Class Methods

included(base) click to toggle source
# File lib/lev/handler.rb, line 114
def self.included(base)
  base.extend(ClassMethods)
  base.class_eval do
    include Lev::Routine
  end
end

Protected Instance Methods

authorized?() click to toggle source

Default authorized? implementation. It returns true so that every handler realization has to make a conscious decision about who is authorized to call the handler. To help the common error of forgetting to override this method in a handler instance, we provide an error message when this default implementation is called.

# File lib/lev/handler.rb, line 211
def authorized?
  self.auth_error_details =
    "Access to handlers is prevented by default.  You need to override the " +
    "'authorized?' in this handler to explicitly grant access."
  false
end
exec(options) click to toggle source

This is a method required by Lev::Routine. It enforces the steps common to all handlers.

# File lib/lev/handler.rb, line 191
def exec(options)
  self.params = options[:params]
  self.request = options[:request]
  self.caller = options[:caller]
  self.options = options.except(:params, :request, :caller)

  setup
  raise Lev.configuration.security_transgression_error, auth_error_details unless authorized?
  validate_paramified_params
  handle unless errors?
end
setup() click to toggle source

Default setup implementation – a no-op

# File lib/lev/handler.rb, line 204
def setup; end
validate_paramified_params() click to toggle source

Helper method to validate paramified params and to transfer any errors into the handler.

# File lib/lev/handler.rb, line 222
def validate_paramified_params
  self.class.paramify_methods.each do |method|
    params = send(method)
    transfer_errors_from(params, TermMapper.scope(params.group)) if !params.valid?
  end
end