使用ActiveRecord,是否有办法在after_update期间获取logging的旧值

安装使用一个简单的例子:我有一个表( Totals ),其中包含每个logging的amount列的总和在第二个表( Things )。

当一个thing.amount得到更新时,我想简单地将旧值和新值之间的差异添加到total.sum

现在我在self.amount期间减去self.amount并在after_update期间添加after_update 。 这使得WAY对更新成功的信任度过高。

约束:我不想简单地重新计算所有交易的总和。

问题:很简单,我想在after_updatecallback期间访问原始值。 你有什么办法做到这一点?

更新:我要和Luke Francl的想法一起去。 在after_updatecallback期间,你仍然可以访问self.attr_was值,这正是我想要的。 我也决定采用after_update实现,因为我想在模型中保留这种逻辑。 这样,不pipe我今后如何决定更新事务,我都会知道我正在更新事务的总和。 感谢大家的实施build议。

同样,每个人都在谈论交易。

那说…

Rails 2.1的ActiveRecord跟踪一个对象的属性值。 所以如果你有一个属性total ,你将有一个total_changed? 方法和一个返回旧值的total_was方法。

没有必要添加任何东西到你的模型来跟踪这个了。

更新:这是ActiveModel :: Dirty所要求的文档。

其他一些人提到在交易中包装所有这些,但我认为这是为你做的; 你只需要通过引发after_ *callback中的错误来触发回滚。

请参阅http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html

保存,保存!或销毁调用的整个callback链在事务中运行。 这包括after_ *钩子。 如果一切顺利,一旦链完成,COMMIT就会被执行。

如果before_ *callback取消了动作,则发出ROLLBACK。 你也可以在任何callback中触发一个ROLLBACK引发exception,包括after_ *钩子。 但是,请注意,在这种情况下,客户端需要知道它,因为普通的保存会引发这样的exception,而不是悄悄地返回错误。

要获得所有更改的字段,分别使用它们的旧值和新值:

 person = Person.create!(:name => 'Bill') person.name = 'Bob' person.save person.changes # => {"name" => ["Bill", "Bob"]} 

将“_was”附加到您的属性将在保存数据之前为您提供以前的值。

这些方法被称为脏方法方法。

干杯!

ActiveRecord :: Dirty是一个内置到ActiveRecord中的模块,用于跟踪属性更改。 所以你可以使用thing.amount_was来获得旧的价值。

将此添加到您的模型中:

 def amount=(new_value) @old_amount = read_attribute(:amount) write_attribute(:amount,new_value) end 

然后在after_update代码中使用@old_amount。

首先,你应该在交易中这样做,以确保你的数据被写在一起。

要回答你的问题,你可以在before_update中设置一个成员variables为旧值,然后你可以在after_update中访问,但是这不是一个很好的解决scheme。

想法1:将数据库事务中的更新包装起来,这样如果更新失败,总表不会被更改: ActiveRecord Transactions docs

想法2:在before_update期间存储@old_total中的旧值。