按条件的状态机事件不起作用

时间:2012-12-25 20:18:57

标签: ruby-on-rails rspec lambda state-machine

只有当给定参数(代码)与对象属性(temporary_code)匹配时,我才需要state_machine事件来提供转换。

当我测试这段代码时:

class User < ActiveRecord::Base

  def initialize
    @temporary_code = 'right'
  end

  state_machine :initial => :inactive do
    event :activate! do
      transition :inactive => :active, :if => lambda{ |code| code == @temporary_code }
    end

    state :inactive do
      def active?
        false
      end
    end

    state :active do
      def active?
        true
      end
    end
  end
end

但无论代码是什么,它都不会进行转换。下面的Rspec测试返回错误:

describe "activation" do
  let(:user) { User.create }
  before { user.activate!('right') }
  specify { user.should be_active }
end

它有什么问题?

1 个答案:

答案 0 :(得分:2)

当引用像@temporary_code这样的实例变量时,即使尚未提及/定义/初始化,也总会得到结果。所以我认为正在发生的是你引用@temporary_code,但它总是nil,因为分配给:if的lambda不是在User实例的上下文中执行的,而是而是在状态机被“编译”的类的实例中。

现在你的代码中有一些奇怪的东西:你已经定义了

transition :inactive => :active, :if => lambda {|code| code == @temporary_code}

但传递给lambda的内容实际上是当前的user。所以

transition :inactive => :active, :if => lambda {|user| ... }

会更合适。

据我所知,state_machine gem没有提供直接的方法来使转换依赖于参数。所以我认为你应该把它带到外面并将以下内容添加到User类中:

attr_accessor :temporary_code
attr_accessor :code

然后将转换更改为

transition :inactive => :active, 
           :if => lambda {|user| user.code == user.temporary_code}

并让调用activate!的代码首先设置temporary_code