ruby-on-rails - rails执行sql - rails数据库



使用ActiveRecord,有没有办法在after_update期间获取记录的旧值 (6)

使用一个简单的例子进行设置:我有一个表( Totals ),它保存第二个表( Things )中每个记录的amount列的总和。

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

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

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

问题:很简单,我想在after_update回调期间访问原始值。 你有什么方法可以做到这一点?

更新:我将采用Luke Francl的想法。 在after_update回调期间,您仍然可以访问self.attr_was值,这正是我想要的。 我还决定使用after_update实现,因为我想在模型中保留这种逻辑。 这样,无论我将来如何决定更新交易,我都知道我正在更新交易总和。 感谢大家的实施建议。

https://src-bin.com


Answer #1

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


Answer #2

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

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

save,save!或destroy调用的整个回调链在事务中运行。 这包括after_ * hooks。 如果一切顺利,一旦链完成就执行COMMIT。

如果before_ *回调取消了该动作,则发出ROLLBACK。 您还可以在任何回调中触发ROLLBACK引发异常,包括after_ * hooks。 但请注意,在这种情况下,客户端需要知道它,因为普通的保存会引发此类异常,而不是静静地返回false。


Answer #3

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

这些方法称为ActiveModel::Dirty方法。

干杯!


Answer #4

将此添加到您的模型:

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

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


Answer #5

要分别使用旧值和新值获取所有已更改的字段:

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

Answer #6

首先,您应该在事务中执行此操作以确保将数据一起写入。

要回答您的问题,您可以将成员变量设置为before_update中的旧值,然后您可以在after_update中访问该值,但这不是一个非常优雅的解决方案。





callback