Module: StateMachine::EvalHelpers
- Included in:
- Branch, Callback, Machine, StateContext
- Defined in:
- lib/state_machine/eval_helpers.rb
Overview
Provides a set of helper methods for evaluating methods within the context of an object.
Instance Method Summary collapse
-
#evaluate_method(object, method, *args, &block) ⇒ Object
Evaluates one of several different types of methods within the context of the given object.
Instance Method Details
#evaluate_method(object, method, *args, &block) ⇒ Object
Evaluates one of several different types of methods within the context of the given object. Methods can be one of the following types:
-
Symbol
-
Method / Proc
-
String
Examples
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
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)
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/state_machine/eval_helpers.rb', line 53 def evaluate_method(object, method, *args, &block) case method when Symbol klass = (class << object; self; end) args = [] if (klass.method_defined?(method) || klass.private_method_defined?(method)) && object.method(method).arity == 0 object.send(method, *args, &block) when Proc, Method args.unshift(object) arity = method.arity # Procs don't support blocks in < Ruby 1.9, so it's tacked on as an # argument for consistency across versions of Ruby if block_given? && Proc === method && arity != 0 if [1, 2].include?(arity) # Force the block to be either the only argument or the 2nd one # after the object (may mean additional arguments get discarded) args = args[0, arity - 1] + [block] else # Tack the block to the end of the args args << block end else # These method types are only called with 0, 1, or n arguments args = args[0, arity] if [0, 1].include?(arity) end method.is_a?(Proc) ? method.call(*args) : method.call(*args, &block) when String eval(method, object.instance_eval {binding}, &block) else raise ArgumentError, 'Methods must be a symbol denoting the method to call, a block to be invoked, or a string to be evaluated' end end |