Overview
This module 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:
-
FSM -> the finite state machine class
-
FSMState -> the state class
- Author
-
Md. Imrul Hassan ([email protected])
- Copyright
-
Copyright: Md. Imrul Hassan, 2013
Features
Apart from having support for states and events, this module offers the following features:
-
Default state
-
Default event for each state
-
Entry and exit events for each state
-
DSL like coding style
-
Access to state variables (including @state and @event) inside event blocks. Currently the state variables can only be shared among event blocks of the same state.
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) # :stopped is the default state to fall back
fsm.build do # the states and events can be configured within the build block
state :stopped do # the events can be setup within the state block for :stopped state
event :open do # the event block is run when the event :open is triggered
puts "[Stopped]: Door Opened"
:open # the return value of the event block, :open, is the next state
end
event :start do
puts "[Stopped]: Started"
:started
end
end
state :open do
event :close do
puts "[#{@state}]: Door #{@event}" # the event block has access to state variables such as @state and @event
:stopped
end
end
state :started do
event :open do
@open_time = Time::now # new state variables can be defined
puts "[Started]: Door Opened"
:open
end
event :stop do
puts "The door was opened at #{@open_time}" # state variables from other event blocks can be used
puts "[Started]: Door Stopped after #{elapsed_time}"
:stopped
end
end
end
fsm.run do # the events can be triggered from the run block
event :start
event :open
event :close
event :start
event :stop
end
puts fsm
Status
The module works as it is, but further testing and documentation is needed. 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.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.
-