轨道上的 Ruby - 按条件列出的状态机事件不起作用



我需要一个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

相关内容

  • 没有找到相关文章

最新更新