peter-murach / finite_machine恢复持久状态

时间:2015-06-25 03:29:08

标签: ruby state-machine

使用来自Piotr Murach的Ruby finite machine gem。

想要以持久(存储)状态恢复状态机。该文档教授初始状态,并从ActiveRecord模型恢复状态。

我能找到的只是让我定义初始状态的DSL,或定义转换到初始状态的事件。两者都要求我在编码时定义初始状态。

fm = FiniteMachine.define do
  initial :red

fm = FiniteMachine.define do
  events {
    event :start, :none   => :red

在实践中,我正在定义一个“独立”的行,

class Engine < FiniteMachine::Definition
  initial :neutral

我想要的是在该类的初始值设定项中定义初始状态,如:

class Engine < FiniteMachine::Definition
     def initialize(car, state)
       initial state
       target car
     end

然而,这不起作用。初始化后,我将:none作为当前状态。

找到restore!方法和文档中有关使用ActiveRecord保持状态的部分。尝试过以下几点:

class Engine < FiniteMachine::Definition
     def initialize(car, state)
       restore! state
       target car
     end

然而,构造函数在其上调用FiniteMachine::StateMachine时返回类newnew方法接受任意数量的参数,并且永远不会调用类的任何initialize方法。它返回一个不同的类。

以下是该程序的输出:

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)

该计划:

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}"

1 个答案:

答案 0 :(得分:1)

更好的方法是创建一个状态机factory method,它通过FiniteMachine.define使用DSL

以下是该程序的输出:

CREATING MACHINE with Light in state green
GSM class is FiniteMachine::StateMachine
GSM current state is green
GSM state after stop is red
Light state after stop is red

该计划:

require 'finite_machine'

class LightMachineFactory
  def self.create_machine(light)
    FiniteMachine.define do
      puts "CREATING MACHINE with #{light}"
      initial light.state
      target light

      events {
        event :start, :red => :green
        event :stop, :green => :red
      }

      callbacks {
        on_enter { |event| target.state = event.to }
      }
    end
  end
end

class Light
  attr_accessor :state
  def initialize
    @state = 'green'
  end
  def to_s
    "Light in state #{state}"
  end
  def state
    @state.to_sym
  end
end

light = Light.new
gsm = LightMachineFactory.create_machine(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}"

此内容由Gem的Github源代码库中的(my)closed issue共享。 (对于更多的使用问题而不是问题,这是一个更好的论坛。)