class StateMachine::State

Attributes

entry_actions[RW]

@return [Array] an array of Proc objects called when entering

the state.
exit_actions[RW]

@return [Array] an array of Proc objects called when exiting

the state.
name[RW]

@return [String] the state’s name. Only used in debug log output.

state_machine[R]

@return [StateMachine::Base] the FSM that the state belongs to.

symbol[R]

@return [Symbol] The state’s identifying symbol.

transition_map[R]

@return [Hash] The state machine’s internal transition map (event

types -> event values -> possible transitions)

@example

{
  :on => {
    :some_event => [transition1, transition2, ...],
    :other_event => [transition3, transition4, ...],
  },
  :after => {
    5.0 => [transition5, transition6, ...]
  }
}

Public Class Methods

new(state_machine, options) click to toggle source

Initializes a new State.

@param [StateMachine] state_machine

The state machine that the state belongs to.

@param [Hash] options

Configuration options for the state.

@option options [Symbol] :symbol

The state's identifier.

@option options [String] :name (nil)

The state's name. Only used in debug log output (optional).

@example

StateMachine::State.new state_machine: my_fsm,
  :symbol => :doing_something,
  :name => "doing something very important"

@return [StateMachine::State] a new State object

# File lib/motion-state-machine/state.rb, line 59
def initialize(state_machine, options)
  @state_machine = state_machine
  @symbol = options[:symbol]
  @name = options[:name] || options[:symbol].to_s
  if @symbol.nil? || @state_machine.nil?
    raise ArgumentError, "Missing parameter"
  end

  @transition_map = {}
  @entry_actions = []
  @exit_actions = []
end

Public Instance Methods

register(transition) click to toggle source

@api private Registers a transition in the transition map.

@param [Transition] transition the transition to register.

# File lib/motion-state-machine/state.rb, line 88
def register(transition)
  event_type = transition.class.instance_variable_get(:@event_type)
  event_trigger_value = transition.event_trigger_value

  transition_map[event_type] ||= {}

  transitions =
    (transition_map[event_type][event_trigger_value] ||= [])
  transitions << transition

  transition
end
terminating=(value) click to toggle source
# File lib/motion-state-machine/state.rb, line 79
def terminating=(value)
  @terminating = !!value
end
terminating?() click to toggle source

@return [Boolean] indicates if the state is a termination state.

# File lib/motion-state-machine/state.rb, line 75
def terminating?
  !!@terminating
end

Private Instance Methods

add_transition_map_defined_in(&block) click to toggle source

Adds the outgoing transitions defined in the given block to the state.

# File lib/motion-state-machine/state.rb, line 274
def add_transition_map_defined_in(&block)
  TransitionDefinitionDSL.new self, @state_machine, &block
end
cleanup() click to toggle source

Cleans up references to allow easier GC.

# File lib/motion-state-machine/state.rb, line 318
def cleanup
  @transition_map.each do |type, events_to_transition_arrays|
    events_to_transition_arrays.each do |event, transitions|
      transitions.clear
    end
  end

  @transition_map = nil
  @state_machine = nil
  @entry_actions = nil
  @exit_actions = nil
end
enter!() click to toggle source

Sets the state machine’s current_state to self, calls all entry actions and activates triggering mechanisms of all outgoing transitions.

# File lib/motion-state-machine/state.rb, line 283
def enter!
  @state_machine.current_state = self

  @entry_actions.each do |entry_action|
    entry_action.call(@state_machine)
  end
  @transition_map.each do |type, events_to_transition_arrays|
    events_to_transition_arrays.each do |event, transitions|
      transitions.each(&:arm)
    end
  end
end
exit!() click to toggle source

Sets the state machine’s current_state to nil, calls all exit actions and deactivates triggering mechanisms of all outgoing transitions.

# File lib/motion-state-machine/state.rb, line 301
def exit!
  map = @transition_map
  map.each do |type, events_to_transition_arrays|
    events_to_transition_arrays.each do |event, transitions|
      transitions.each(&:unarm)
    end
  end

  @exit_actions.each do |exit_action|
    exit_action.call(@state_machine)
  end
  @state_machine.current_state = nil
end
guarded_execute(event_type, event_trigger_value) click to toggle source

Executes the registered transition for the given event type and event trigger value, if such a transition exists and it is allowed.

@raise [RuntimeError] if multiple transitions would be allowed at

the same time.
# File lib/motion-state-machine/state.rb, line 339
def guarded_execute(event_type, event_trigger_value)
  @state_machine.raise_outside_initial_queue

  return if terminating?

  if @transition_map[event_type].nil? ||
     @transition_map[event_type][event_trigger_value].nil?
    raise ArgumentError,
      "No registered transition found "\
      "for event #{event_type}:#{event_trigger_value}."
  end

  possible_transitions =
    @transition_map[event_type][event_trigger_value]

  return if possible_transitions.empty?
  allowed_transitions = possible_transitions.select(&:allowed?)

  if allowed_transitions.empty?
    @state_machine.log "All transitions are disallowed for "\
      "#{event_type}:#{event_trigger_value}."
  elsif allowed_transitions.count > 1
    list = allowed_transitions.collect do |t|
      "-> #{t.options[:to]}"
    end
    raise RuntimeError,
      "Not sure which transition to trigger "\
      "when #{symbol} while #{self} (allowed: #{list}). "\
      "Please make sure guard conditions exclude each other."
  else
    transition = allowed_transitions.first
    unless transition.nil?
      transition.send :unguarded_execute
    end
  end

end