Class: FSM::FSM

Inherits:
Object
  • Object
show all
Defined in:
lib/barebone-fsm.rb

Overview

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.

Examples:

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

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(default_state = nil) ⇒ FSM

Creates a new FSM object with an optional default state.

Examples:

Create a new finite state machine without default state

fsm = FSM::FSM.new

Create a new finite state machine with default state

fsm = FSM::FSM.new(:default_state)

Parameters:

  • default_state (Symbol) (defaults to: nil)

    the name for the default state



189
190
191
192
193
194
195
# 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

Instance Attribute Details

#statesObject (readonly)

The list of all the states.



177
178
179
# File 'lib/barebone-fsm.rb', line 177

def states
  @states
end

Instance Method Details

#[]Object #[](state_name) ⇒ Object

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.

Returns the FSMState object with state_name. If it is not setup yet, a new FSMState object is created first and then returned.

Examples:

fsm = FSM::FSM.new
new_state = fsm[:new_state]
print fsm[:new_state].state

Overloads:

  • #[]Object

    The current FSMState object is returned.



227
228
229
230
231
232
233
234
# 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) ⇒ Object Also known as: run

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.

Examples:

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

See Also:



326
327
328
# File 'lib/barebone-fsm.rb', line 326

def build(&build_block)
  self.instance_eval &build_block
end

#event(*event_names) ⇒ Object

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.

Examples:

Triggers two events

state.event(:first_event, :second_event)

Parameters:

  • event_names (Array<Symbol>)

    the list of event names



287
288
289
290
291
292
293
294
295
296
297
298
# 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) ⇒ Object



301
302
303
# File 'lib/barebone-fsm.rb', line 301

def event=(event_name)
  @event = event_name
end

#state(state_name, state_block) ⇒ Object #state(state_name) ⇒ Object #stateObject

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.

Examples:

Setup a state by block

fsm = FSM::FSM.new
new_state = fsm.state(:new_state) do 
  event :an_event => :next_state
end

Create a new state

fsm = FSM::FSM.new
new_state = fsm.state(:new_state)

Return the current state

fsm = FSM::FSM.new
new_state = fsm.state(:new_state)
print fsm.state.state

Overloads:

  • #state(state_name, state_block) ⇒ Object

    Sets up a state with the given state_block parameter.

    Parameters:

    • state_name (Symbol)

      the name of the state to set up

    • state_block (block)

      the block of code to setuo the state

  • #state(state_name) ⇒ Object

    Create and/or return a state object.

    Parameters:

    • state_name (Symbol)

      the name of the state

  • #stateObject

    Return current state object.



269
270
271
272
273
274
275
# 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_sObject

A String representation of the FSM object.



200
201
202
203
204
205
206
207
# File 'lib/barebone-fsm.rb', line 200

def to_s() 
  "FSM" + 
    ": {" + 
      @states.values.map{ |st| 
        (st.state==@state ? ">" : "") + st.to_s
      }.join(', ') + 
    "}" 
end