2009-10-19 57 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宝石)会更好。

相关问题