我需要一个state_machine事件,只有当给定的参数(代码)匹配对象属性(temporary_code)时才提供转换。
当我测试这个代码时:
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
怎么了?
当您引用像@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