使用一个简单示例进行设置:我有一个table(Totals
),它保存amount
第二个表(Things
)中每个记录的列的总和.
当thing.amount
更新时,我想简单地添加旧值和新值之间的差异total.sum
.
现在我正在减去self.amount
期间before_update
并self.amount
在期间添加after_update
.这使得WAY过于信任更新成功.
约束: 我不想简单地重新计算所有交易的总和.
问题:很简单,我想在after_update
回调期间访问原始值.你有什么方法可以做到这一点?
更新:我将采用Luke Francl的想法.在after_update
回调期间,您仍然可以访问self.attr_was
我想要的值.我还决定使用after_update
实现,因为我想在模型中保留这种逻辑.这样,无论我将来如何决定更新交易,我都知道我正在更新交易总和.感谢大家的实施建议.
同样每个人都在谈论交易.
那说......
从Rails 2.1开始的ActiveRecord跟踪对象的属性值.因此,如果您有一个属性total
,您将拥有一个返回旧值的total_changed?
方法和total_was
方法.
您无需在模型中添加任何内容即可跟踪此情况.
更新:这是ActiveModel :: Dirty的文档.
在属性中附加"_was"将在保存数据之前为您提供先前的值.
这些方法称为脏方法方法.
干杯!
其他一些人提到在交易中包装所有这些,但我认为这是为你完成的; 您只需要通过在after_*回调中引发错误异常来触发回滚.
请参阅http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html
save,save!或destroy调用的整个回调链在事务中运行.这包括after_*hooks.如果一切顺利,一旦链完成就执行COMMIT.
如果before_*回调取消了该动作,则发出ROLLBACK.您还可以在任何回调中触发ROLLBACK引发异常,包括after_*hooks.但请注意,在这种情况下,客户端需要知道它,因为普通的保存会引发此类异常,而不是静默地返回false.
要分别使用旧值和新值获取所有已更改的字段:
person = Person.create!(:name => 'Bill') person.name = 'Bob' person.save person.changes # => {"name" => ["Bill", "Bob"]}