如果触发关联回调,如何防止模型回调被触发? [英] How do I prevent a model callback from being triggered if an association callback is triggered?
问题描述
我有一个模型 PositionGroup
,该模型 has_many:positions
.
I have a model PositionGroup
that has_many :positions
.
无论何时添加或保存位置,我都希望它更新 PositionGroup
上的属性.例如.将新职位添加到 PositionGroup
后,我想将 position.volume
添加到现有的 position_group.total_units
中.
Whenever a position is added or saved, I want it to update an attribute on PositionGroup
. E.g. when a new position has been added to a PositionGroup
, I would like to add the position.volume
to the existing position_group.total_units
.
因此,请考虑以下示例:
So, consider the following example:
pg.total_units = 100
position2.volume = 50
# then pg.total_units should be updated to:
pg.total_units = 150
我知道我可以通过关联回调来做到这一点,这很好.
I realize I can do this with an association callback and that’s fine.
问题是,当我想更新前一个头寸的交易量时会发生什么.如果我添加 before_save
或 after_save
,那么该回调也会在触发 after_add
回调后被触发-从而人为地夸大了 pg.total_units
图.
The issue is, what happens when I want to update a previous position’s volume. If I add a before_save
or an after_save
, then that callback will also be triggered after the after_add
callback is triggered -- thereby artificially inflating the pg.total_units
figure.
我该如何解决?
推荐答案
如果我正确理解了这个问题,这是防止这种人为膨胀的一种天真的方法:
If I understood the question correctly, here's one naive way to prevent that artificial inflation:
class Position < ApplicationRecord
belongs_to :position_group
before_save :update_position_group_total_units
def update_position_group_total_units
delta = volume - (volume_was || 0)
position_group.update!(total_units: position_group.total_units + delta)
end
end
class PositionGroup < ApplicationRecord
has_many :positions
end
在此处查看文档: https://api.rubyonrails.org/classes/ActiveModel/Dirty.html
需要说明的是,如果保存由于某种原因而失败,position_group仍将更新,从而导致另一种错误的计算.
我最喜欢触摸方式,如您所见:
class Position < ApplicationRecord
belongs_to :position_group, touch: true
end
class PositionGroup < ApplicationRecord
has_many :positions
after_touch :recompute_total_units
private
def recompute_total_units
update_column(:total_units, positions.sum(:volume))
end
end
这篇关于如果触发关联回调,如何防止模型回调被触发?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!