2009-10-19 63 views
71

我想在保存模型後執行的rails中創建回調函數。如何從模型中檢測屬性更改?

我有這樣的模型中,具有屬性「狀態」取決於權利要求的狀態,可能的值之前,背書,覈准這改變要求,拒絕

該數據庫具有「國家」用默認'pending'的值。

我想在第一次創建模型或從一個狀態更新到另一個狀態之後執行某些任務,具體取決於它從哪個狀態變化而來。

我的想法是在模型的函數:

after_save :check_state 

    def check_state 
     # if status changed from nil to pending (created) 
     do this 

     # if status changed from pending to approved 
     performthistask 
    end 

我的問題是我怎麼檢查模型中的變化之前,前值?

回答

148

你應該看看ActiveModel::Dirty模塊: 你應該能夠對您的請求模型執行以下操作:

claim.status_changed? # returns true if 'status' attribute has changed 
claim.status_was  # returns the previous value of 'status' attribute 
claim.status_change # => ['old value', 'new value'] returns the old and 
         # new value for 'status' attribute 

claim.name = 'Bob' 
claim.changed # => ["name"] 
claim.changes # => {"name" => ["Bill", "Bob"]} 

哦! Rails的樂趣!

+4

保存模型後,這是行不通的,這是他要求的。 – 2012-06-27 15:37:40

+3

@TomRossi,'dirty'調用在'after_save'中工作(都在Rails 2.3和3.x中)。我已經使用過好幾次了。 – 2012-06-27 15:54:17

+8

@TomRossi,在提交後重新設置髒標誌,所以它們不會在Rails 3.x中引入的'after_commit'回調中可用。他們當然會在'after_save'中工作。 – 2012-06-27 15:56:07

3

,我建議你在現有的狀態機插件之一看看:

無論是一個可以讓你的狀態之間建立的狀態和轉換。非常有用和簡單的方式來處理您的要求。

+0

我給rubyist-aasm一試。 可以說我有 類權利要求:enter_pending DEF enter_pending 通告。deliver_pending_notification(self) end end 而且我的數據庫中的狀態字段的默認值是「pending」。 如果我在沒有填寫status字段的情況下執行Claim.create(以便它將運行'pending'),AASM是否會運行'enter_pending'方法? – 2009-10-19 02:47:44

33

您可以使用此

self.changed 

它返回該記錄

改變所有列的一個陣列,你也可以使用

self.changes 

它返回改變列的哈希並在結果之前和之後作爲陣列

+4

只需稍加說明,在這些上不需要使用'self.' - 你可以說'changed'和「變化」。 – user664833 2014-08-29 00:38:43

0

我見過這個問題在上升很多地方,所以我爲它寫了一個小小的rubygem,以使代碼更好一點(並且避免在任何地方發生數百萬條if/else語句):https://github.com/ronna-s/on_change。 我希望有所幫助。

0

使用經過良好測試的解決方案(如state_machine寶石)會更好。

相關問題