如果触发关联回调,如何防止模型回调被触发?

问题描述 投票:0回答:2

我有一个模型PositionGroup那个has_many :positions

[无论何时添加或保存位置,我都希望它更新PositionGroup上的属性。例如。当新位置已添加到PositionGroup时,我想将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

我知道我可以通过关联回调来做到这一点,这很好。

问题是,当我想更新前一个头寸的交易量时会发生什么。如果添加before_saveafter_save,则在触发after_add回调后也会触发该回调-从而人为抬高pg.total_units数字。

我该如何解决?

ruby-on-rails callback ruby-on-rails-5
2个回答
0
投票

我想出了一个解决方案。

[基本上,而不是使用许多after_save, before_save & after_add回调,我只是在一种模型上使用touch: true而在另一种模型上使用after_touch。那解决了我所有的问题。

为了更加清楚,我在Position模型上添加了:

belongs_to :position_group, touch: true

然后在我的PositionGroup模型上,我添加了:

after_touch :recompute_total_units

  private

  def recompute_total_units
    update_column(:total_units, positions.sum(:volume))
  end

Voila。


0
投票

如果我正确理解了这个问题,这是防止这种人为膨胀的一种天真的方法:

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
© www.soinside.com 2019 - 2024. All rights reserved.