Class: StateMachine::ConditionProxy

Inherits:
Module
  • Object
show all
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(options, &block)
      validations << options
    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

Methods included from EvalHelpers

#evaluate_method

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
# File 'lib/state_machine/condition_proxy.rb', line 60

def method_missing(*args, &block)
  # Get the configuration
  if args.last.is_a?(Hash)
    options = args.last
  else
    args << options = {}
  end
  
  # Get any existing condition that may need to be merged
  wrap_condition(options, true)

  # Evaluate the method on the original class with the condition proxied
  # through
  @klass.send(*args, &block)
end