Class: Finity::Machine

Inherits:
Object
  • Object
show all
Defined in:
lib/finity/machine.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(klass, options = {}, &block) ⇒ Machine

Initialize a new state machine within the provided class and define methods for querying the current state and initiating transitions. The current state must be bound to the including instance, otherwise there may be problems due to caching between requests.



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/finity/machine.rb', line 31

def initialize klass, options = {}, &block
  @klass, @states, @events = klass, {}, {}
  instance_eval &block if block_given?
  @initial = current = options.delete(:initial) || initial
  @klass.send :define_method, :current do |*args|
    unless self.instance_variable_defined? :@current
      self.instance_variable_set :@current, current
    end
    self.instance_variable_get :@current
  end
  @klass.send :define_method, :event! do |*args|
    self.instance_variable_set :@current, (
      klass.finity.update self, self.current, *args
    )
  end
  @klass.send :define_method, :state? do |*args|
    klass.finity.current.name.eql? *args
  end
end

Instance Attribute Details

#eventsObject

Returns the value of attribute events.



25
26
27
# File 'lib/finity/machine.rb', line 25

def events
  @events
end

#statesObject

Returns the value of attribute states.



25
26
27
# File 'lib/finity/machine.rb', line 25

def states
  @states
end

Instance Method Details

#event(name, options = {}, &block) ⇒ Object

Register an event and evaluate the block for transitions.



62
63
64
# File 'lib/finity/machine.rb', line 62

def event name, options = {}, &block
  @events[name] = Event.new name, options, &block
end

#initialObject

Return the name of the initial state.



52
53
54
# File 'lib/finity/machine.rb', line 52

def initial
  @initial ||= @states.keys.first unless @states.first.nil?
end

#state(name, options = {}) ⇒ Object

Register a state.



57
58
59
# File 'lib/finity/machine.rb', line 57

def state name, options = {}
  @states[name] = State.new name, options
end

#update(object, current, event) ⇒ Object

An event occured, so update the state machine by evaluating the transition functions and notify the left and entered state.



68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/finity/machine.rb', line 68

def update object, current, event
  now ||= @states[current]
  if state = @events[event].handle(object, now)
    if @states[state].nil?
      raise InvalidState, "Invalid state #{state}"
    end
    now.leave object
    now = @states[current = state]
    now.enter object
  end
  current
end