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
Provided for development / debugging purposes – gives a way to pass information in a raised security transgression when authorized? is false
Public Class Methods
# 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
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
Default setup implementation – a no-op
# File lib/lev/handler.rb, line 204 def setup; end
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