Module | StateMachine::EvalHelpers |
In: |
lib/state_machine/eval_helpers.rb
|
Provides a set of helper methods for evaluating methods within the context of an object.
Evaluates one of several different types of methods within the context of the given object. Methods can be one of the following types:
Below are examples of the various ways that a method can be evaluated on an object:
class Person def initialize(name) @name = name end def name @name end end class PersonCallback def self.run(person) person.name end end person = Person.new('John Smith') evaluate_method(person, :name) # => "John Smith" evaluate_method(person, PersonCallback.method(:run)) # => "John Smith" evaluate_method(person, Proc.new {|person| person.name}) # => "John Smith" evaluate_method(person, lambda {|person| person.name}) # => "John Smith" evaluate_method(person, '@name') # => "John Smith"
Additional arguments can be passed to the methods being evaluated. If the method defines additional arguments other than the object context, then all arguments are required.
For example,
person = Person.new('John Smith') evaluate_method(person, lambda {|person| person.name}, 21) # => "John Smith" evaluate_method(person, lambda {|person, age| "#{person.name} is #{age}"}, 21) # => "John Smith is 21" evaluate_method(person, lambda {|person, age| "#{person.name} is #{age}"}, 21, 'male') # => ArgumentError: wrong number of arguments (3 for 2)
# File lib/state_machine/eval_helpers.rb, line 53 53: def evaluate_method(object, method, *args, &block) 54: case method 55: when Symbol 56: object.method(method).arity == 0 ? object.send(method, &block) : object.send(method, *args, &block) 57: when Proc, Method 58: args.unshift(object) 59: arity = method.arity 60: limit = [0, 1].include?(arity) ? arity : args.length 61: 62: # Procs don't support blocks in < Ruby 1.8.6, so it's tacked on as an 63: # argument for consistency across versions of Ruby (even though 1.9 64: # supports yielding within blocks) 65: if block_given? && Proc === method && arity != 0 66: if [1, 2].include?(arity) 67: # Force the block to be either the only argument or the 2nd one 68: # after the object (may mean additional arguments get discarded) 69: limit = arity 70: args.insert(limit - 1, block) 71: else 72: # Tack the block to the end of the args 73: limit += 1 unless limit < 0 74: args.push(block) 75: end 76: end 77: 78: method.call(*args[0, limit], &block) 79: when String 80: eval(method, object.instance_eval {binding}, &block) 81: else 82: raise ArgumentError, 'Methods must be a symbol denoting the method to call, a block to be invoked, or a string to be evaluated' 83: end 84: end