只有当给定参数(代码)与对象属性(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
它有什么问题?
答案 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
。