Overview

This module, barebone-fsm, implements a basic finite-state machine (FSM). An FSM consists of a finite number of states, with one of them being the current state of the FSM. Transitions are defined between states, which are triggered on events. For details on FSM, see this wiki page: FSM.

The motivation behind the module was to implement a very basic barebone FSM in Ruby. Features are kept at minimum as well as the code. Only two classes for the FSM are defined as the following:

The FSM Module when included in a class also provides few convenience methods. For further details see the README file.

Author

Md. Imrul Hassan ([email protected])

Copyright

Copyright © 2013, Md. Imrul Hassan

License

Barebone-fsm is released under the MIT license

Features

Apart from having support for states and events, this module offers the following features:

  1. Default state

  2. Default event for each state

  3. Entry and exit events for each state

  4. DSL like coding style

  5. Access to state variables (including @state and @event) inside event blocks

  6. The module when included in a Class, provides methods to setup the state machine and trigger events

  7. Dynamic methods generated for the Class to check states, events and trigger events.

Usage

The FSM can be setup and triggered Succinctly using Domain Specific Language(DSL) like coding style. There are two methods to build and run which are defined for both FSM and FSMState classes. These methods, #build and #run, are alias of each other and can be used interchangebly. A basic fintite-state machine for a microwave is simulated in the following example:

fsm = FSM::FSM.new(:stopped)
fsm.build do
  state :stopped do
    event :open do
      puts "[Stopped]: Door Opened"
      :open
    end
    event :start do
      puts "[Stopped]: Started"
      :started
    end
  end
  state :open do
    event :close do
      puts "[#{@state}]: Door #{@event}"
      :stopped
    end
  end
  state :started do
    event :open do
      @open_time = Time::now
      puts "[Started]: Door Opened"
      :open
    end
    event :stop do
      puts "The door was opened at #{@open_time}"
      puts "[Started]: Door Stopped after #{elapsed_time}"
      :stopped
    end
  end
end
fsm.run do
  event :start
  event :open
  event :close
  event :start
  event :stop
end

Status

The module works as it is, I have added some testing and documentation; it may be expanded. The api is not stable yet, it may go trhough lots of changes before the first stable version is released. I am open to any suggestion or request to support custom features.

Changes

  • Version: 0.0.3

    • Added Module level methods for easy access to states and events.

    • Added documentations for all the methods.

    • Added Module level dynamic methods to check states, events and to trigger events.

    • Added some testing codes using RSpec.

  • Version: 0.0.2

    • State variables defined in other states can be accessed in the event block as well.

  • Version: 0.0.1.3

    • Minor fixes on the usage examples.

  • Version: 0.0.1.2

    • @state instance variable for FSM is dropped in favour of the #state instance method.

    • #state method and index operator [] now accept nil arguement for state name, which returns the current state.

    • Two methods #build and #run are added to FSM and FSMState classes to support DSL like features.

    • Explicit parameter passing for the event blocks is no longer available. Instead the block code for the events now have access to all instance variables of FSMState class such as @state and @event.