Using finite machine gem for Ruby from Piotr Murach.
Would like to restore the state machine with a persisted (stored) state. The documentation teaches the initial state, and restoring state from and ActiveRecord model.
All I've been able to find is the DSL that lets me define an initial state, or define an event that transitions to an initial state. Both require me to define the initial state at coding time.
fm = FiniteMachine.define do
initial :red
or
fm = FiniteMachine.define do
events {
event :start, :none => :red
In practice, I'm defining a "standalone" along the lines of,
class Engine < FiniteMachine::Definition
initial :neutral
What I'd like is to define the initial state in the initializer for that class, something like:
class Engine < FiniteMachine::Definition
def initialize(car, state)
initial state
target car
end
However that does not work. I get :none
as the current state after initialization.
Found the restore!
method and the section in the doc about persisting state with ActiveRecord. Tried something along the lines of:
class Engine < FiniteMachine::Definition
def initialize(car, state)
restore! state
target car
end
However the constructor returns a class FiniteMachine::StateMachine
when called new
on it. The new
method takes any number of arguments, and any initialize
method of the class is never called. It returns a different class.
Here is output from the program that follows:
GSM class is FiniteMachine::StateMachine
GSM current state is red
.gems/gems/finite_machine-0.10.1/lib/finite_machine/state_machine.rb:259:in `valid_state?': inappropriate current state 'red' (FiniteMachine::InvalidStateError)
The program:
require 'finite_machine'
class GenericStateMachine < FiniteMachine::Definition
initial :red
def initialize(light)
puts "INITIALIZER WITH #{light}"
super
restore! light.state
target light
end
events {
event :start, :red => :green
event :stop, :green => :red
}
callbacks {
on_enter { |event| target.state = event.to }
}
end
class Light
attr_accessor :state
def initialize
state = 'green'
end
def to_s
"Light in state #{state}"
end
end
light = Light.new
gsm = GenericStateMachine.new(light)
puts "GSM class is #{gsm.class.to_s}"
puts "GSM current state is #{gsm.current}"
gsm.stop
puts "GSM state after stop is #{gsm.current}"
puts "Light state after stop is #{light.state}"
What works better is to make a state machine factory method, that uses the DSL via
FiniteMachine.define
Here is output from the program that follows:
The program:
This content is shared from (my) closed issue in the Github source repository for the Gem. (This is a better forum for what is more a usage question than an issue.)