class StateMachine::State
Attributes
@return [Array] an array of Proc
objects called when entering
the state.
@return [Array] an array of Proc
objects called when exiting
the state.
@return [String] the state’s name. Only used in debug log output.
@return [StateMachine::Base] the FSM that the state belongs to.
@return [Symbol] The state’s identifying symbol.
@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
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
@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
# File lib/motion-state-machine/state.rb, line 79 def terminating=(value) @terminating = !!value end
@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
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
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
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
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
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