Class: StateMachine::ConditionProxy
- Inherits:
-
Module
- Object
- Module
- StateMachine::ConditionProxy
- Includes:
- EvalHelpers
- Defined in:
- lib/state_machine/condition_proxy.rb
Overview
Represents a type of module in which class-level methods are proxied to another class, injecting a custom :if condition along with method.
This is used for being able to automatically include conditionals which check the current state in class-level methods that have configuration options.
Examples
class Vehicle
class << self
attr_accessor :validations
def validate(, &block)
validations <<
end
end
self.validations = []
attr_accessor :state, :simulate
def moving?
self.class.validations.all? {|validation| validation[:if].call(self)}
end
end
In the above class, a simple set of validation behaviors have been defined. Each validation consists of a configuration like so:
Vehicle.validate :unless => :simulate
Vehicle.validate :if => lambda {|vehicle| ...}
In order to scope conditions, a condition proxy can be created to the Vehicle class. For example,
proxy = StateMachine::ConditionProxy.new(Vehicle, lambda {|vehicle| vehicle.state == 'first_gear'})
proxy.validate(:unless => :simulate)
vehicle = Vehicle.new # => #<Vehicle:0xb7ce491c @simulate=nil, @state=nil>
vehicle.moving? # => false
vehicle.state = 'first_gear'
vehicle.moving? # => true
vehicle.simulate = true
vehicle.moving? # => false
Instance Method Summary collapse
-
#initialize(klass, condition) ⇒ ConditionProxy
constructor
Creates a new proxy to the given class, merging in the given condition.
-
#method_missing(*args, &block) ⇒ Object
Hooks in condition-merging to methods that don’t exist in this module.
Methods included from EvalHelpers
Constructor Details
#initialize(klass, condition) ⇒ ConditionProxy
Creates a new proxy to the given class, merging in the given condition
54 55 56 57 |
# File 'lib/state_machine/condition_proxy.rb', line 54 def initialize(klass, condition) @klass = klass @condition = condition end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(*args, &block) ⇒ Object
Hooks in condition-merging to methods that don’t exist in this module
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 86 87 88 89 90 91 92 |
# File 'lib/state_machine/condition_proxy.rb', line 60 def method_missing(*args, &block) # Get the configuration if args.last.is_a?(Hash) = args.last else args << = {} end # Get any existing condition that may need to be merged if_condition = .delete(:if) unless_condition = .delete(:unless) # Provide scope access to configuration in case the block is evaluated # within the object instance proxy = self proxy_condition = @condition # Replace the configuration condition with the one configured for this # proxy, merging together any existing conditions [:if] = lambda do |*args| # Block may be executed within the context of the actual object, so # it'll either be the first argument or the executing context object = args.first || self proxy.evaluate_method(object, proxy_condition) && Array(if_condition).all? {|condition| proxy.evaluate_method(object, condition)} && !Array(unless_condition).any? {|condition| proxy.evaluate_method(object, condition)} end # Evaluate the method on the original class with the condition proxied # through @klass.send(*args, &block) end |