如果触发关联回调,如何防止模型回调被触发? [英] How do I prevent a model callback from being triggered if an association callback is triggered?

查看:55
本文介绍了如果触发关联回调,如何防止模型回调被触发?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个模型 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆