2012-12-25 21 views
2

只有當給定參數(代碼)與對象屬性(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 

它有什麼問題?

回答

2

當引用像@temporary_code這樣的實例變量時,即使尚未提及/定義/初始化,您仍然會得到結果。所以我認爲發生的是你參考@temporary_code,但它總是nil,因爲分配給:if的lambda不在用戶的實例的上下文中執行,而是在狀態機所屬的類的實例內執行已被「編譯」。

現在有一個在你的代碼奇怪的事情:你已經定義

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

但什麼是傳遞給拉姆達實際上是在當前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的代碼。

+0

感謝您的回答。 不幸的是,當我用 \t 事件激活! ...,:if => lambda {| user | ...} \t ,然後嘗試調用它不帶參數(假設當前對象將被定義給出) user.activate!() \t 我收到一個錯誤「錯誤的參數數量(0 1) 」。 現在(作爲一種臨時解決方案)我決定通過添加類激活(無激勵)將授權移動到上一級,其中「激活!」由條件調用。但由於存在安全漏洞,這不是一個理想的方法,我試圖避免。 :( –

+0

我不能重現你描述的行爲,這聽起來像你已經定義了一個單獨的'activate!'方法,它只需要一個參數? – Confusion