2

仅当给定参数(代码)与对象属性(临时代码)匹配时,我才需要 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

它有什么问题?

4

1 回答 1

3

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

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

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

但传递给 lambda 的实际上是 current 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.

于 2012-12-25T21:32:44.677 回答