ruby-on-rails - 如果触发关联回调,如何防止触发模型回调?
问题描述
我有一个PositionGroup
模型has_many :positions
。
每当添加或保存位置时,我希望它更新PositionGroup
. 例如,当一个新的位置被添加到 aPositionGroup
时,我想将它添加position.volume
到现有的position_group.total_units
.
因此,请考虑以下示例:
pg.total_units = 100
position2.volume = 50
# then pg.total_units should be updated to:
pg.total_units = 150
我意识到我可以通过关联回调来做到这一点,这很好。
问题是,当我想更新前一个头寸的交易量时会发生什么。如果我添加 abefore_save
或 an after_save
,则该回调也将在触发回调后after_add
触发 - 从而人为地夸大pg.total_units
数字。
我该如何解决这个问题?
解决方案
如果我正确理解了这个问题,这是防止人为通货膨胀的一种天真的方法:
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
推荐阅读
- javascript - 来自客户端浏览器的 Ping(延迟)请求,而不是来自虚拟主机
- react-final-form - 在加载表单上的字段上显示错误
- python - 添加新的搜索过滤器
- php - 即使数据正确,Ajax Post 也无法正常工作
- ruby - 对于每个用户名,如何使用 Linux useradd 命令关闭读取 CSV 文件来创建用户帐户
- java - java中多个json到xml的高效处理
- c# - 可疑演员表 解决方案中没有继承自两者的类型
- javascript - 创建一个 JavaScript npm 包 - 是否需要提供一个转译的 dist?
- wordpress - 有没有一种快速的方法可以将图像添加到 WooCommerce 商店中的所有产品?
- css - 无法覆盖 CSS