class FSM::FSM
This class implements the finite-state machine. FSM
class exposes the states it contains and can trigger an event. States are created on the fly first time it’s referenced through index operator [] or state
method.
The FSM
state transits to the default state if the latest event does not define the next state. If default state is not set, then state does not change on undefined state. The initial state of the FSM
is the first state mentioned. This can be either the default state if defined or the first referenced state.
@example Setting up finite state machine and triggering events without blocks
fsm = FSM::FSM.new(:default_state) fsm[:default_state].event(:first_event) do puts "The first transition from the default_state to state_name" :state_name end fsm.event :first_event
@example Setting up finite state machine and triggering events with blocks
fsm = FSM::FSM.new fsm.build do state :initial_state do event :an_event => :next_state end end fsm.run do event :an_event end
Attributes
The list of all the states.
Public Class Methods
Creates a new FSM
object with an optional default state. @param default_state [Symbol] the name for the default state
@example Create a new finite state machine without default state
fsm = FSM::FSM.new
@example Create a new finite state machine with default state
fsm = FSM::FSM.new(:default_state)
# File lib/barebone-fsm.rb, line 189 def initialize(default_state=nil) @states = {} if default_state then @default = default_state @states[@default] = FSMState.new(self, @default) end end
Public Instance Methods
Creates and/or returns an FSMState
object. If an FSMState
object with state_name is present, then returns that object. Otherwise, it creates a new FSMState
object first and then returns that object. If state_name is not given, then current state object is returned.
@overload []()
The current FSMState object is returned.
@overload [](state_name) Returns the FSMState
object with state_name. If it is not setup yet, a new FSMState
object is created first and then returned.
@example
fsm = FSM::FSM.new new_state = fsm[:new_state] print fsm[:new_state].state
# File lib/barebone-fsm.rb, line 227 def [](state_name=nil) state_name ||= @state if state_name and not @states.has_key? state_name then @states[state_name] = FSMState.new(self, state_name) @state ||= state_name end @states[state_name] end
The build
/#run method sets up the states and events as DSL code in the build_block. Only state and event methods are supported within the build_block with the name of the state/event and an optional block supplied. The operation for each such line is carried out by the state
/#event method. @see FSM::FSM#state
@see FSM::FSM#event
@example Using block to setup states and trigger events
fsm = FSM::FSM.new fsm.build do state :stopped do event :run => :running end state :running do event :stop => :stopped end end fsm.run do event :run, :stop end
# File lib/barebone-fsm.rb, line 326 def build(&build_block) self.instance_eval &build_block end
Trigger a series of events. The :entry and :exit events are called on the leaving state and the entering state. If the event does not mention the new state, then the state changes to the default state.
@param event_names [Array<Symbol>] the list of event names
@example Triggers two events
state.event(:first_event, :second_event)
# File lib/barebone-fsm.rb, line 287 def event(*event_names) for event_name in event_names do @event = event_name @states[@state].event :exit new_state = @states[@state].event event_name new_state = nil if not @states.has_key? new_state new_state ||= @default new_state ||= @state @state = new_state @states[@state].event :enter end end
@private
# File lib/barebone-fsm.rb, line 301 def event=(event_name) @event = event_name end
Sets up and/or returns an FSMState
object. It sets up a new state with all its events when the state_block is provided. If state_block is missing, then it creates and/or returns an FSMState
object with state_name. If state_name is not given, then current state object is returned.
@overload state(state_name, state_block)
Sets up a state with the given state_block parameter. @param state_name [Symbol] the name of the state to set up @param state_block [block] the block of code to setuo the state
@overload state(state_name)
Create and/or return a state object. @param state_name [Symbol] the name of the state
@overload state()
Return current state object.
@example Setup a state by block
fsm = FSM::FSM.new new_state = fsm.state(:new_state) do event :an_event => :next_state end
@example Create a new state
fsm = FSM::FSM.new new_state = fsm.state(:new_state)
@example Return the current state
fsm = FSM::FSM.new new_state = fsm.state(:new_state) print fsm.state.state
# File lib/barebone-fsm.rb, line 269 def state(state_name=nil, &state_block) if block_given? then self.[](state_name).build &state_block else self.[](state_name) end end
A String representation of the FSM
object.
# File lib/barebone-fsm.rb, line 200 def to_s() "FSM" + ": {" + @states.values.map{ |st| (st.state==@state ? ">" : "") + st.to_s }.join(', ') + "}" end