定义自定义状态机

时间:2012-07-05 07:06:21

标签: ruby-on-rails ruby

我试图让人们可以在类中定义任意工作流程。 Stack Overflow的代码可能太长了,所以我有 a gist

如果您运行代码,前几个测试将起作用,但当它尝试转换到付款状态时,它会检查完整错误对象上的payment_required?方法。我希望它在当前Order实例上检查它,但它(貌似)正在状态机匿名类中寻找该方法。

如何让它在Order实例上正确调用方法?

2 个答案:

答案 0 :(得分:0)

问题在于匿名状态机的定义,围绕第42行:

  order.class.transitions.each { |attrs| transition(attrs) }

这意味着过渡保护在匿名状态机的上下文中而不是在Order类的上下文中进行评估。

一种解决方案是翻译过渡警卫。用这个替换上面的行以通过测试套件:

  order.class.transitions.each do |attrs| 
    if attrs[:if].is_a? Symbol
      if_method = attrs[:if]
      attrs[:if] = lambda { order.send( if_method ) } 
    end

    transition(attrs)
  end

您需要支持所有类型的过渡警卫才能获得完整的解决方案。建议查看完整集StateMachine::EvalHelpers

更正:

正如其他人所提到的,您还需要修复测试套件:

go_to :payment, :if => :payment_required? # Line 107

order.stub :payment_required? => true # Line 142

答案 1 :(得分:0)

我已经通过将状态机定义移动到Spree::Order类来解决这个问题。您可以在this pull request中看到该作品。