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

states[R]

The list of all the states.

Public Class Methods

new(default_state=nil) click to toggle source

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

[](state_name=nil) click to toggle source

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
build(&build_block) click to toggle source

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
Also aliased as: run
event(*event_names) click to toggle source

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
event=(event_name) click to toggle source

@private

# File lib/barebone-fsm.rb, line 301
def event=(event_name)
  @event = event_name
end
run(&build_block)
Alias for: build
state(state_name=nil, &state_block) click to toggle source

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
to_s() click to toggle source

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