Ruby on Rails - 在 accepts_nested_attributes_for 中使用 before_save 计算

8
我有一个发票模型,其中“有多个”发票项目。我有一个表单,允许您创建/编辑发票,并且此表单接受发票项目的嵌套属性。
在我的发票模型中,有一个“total_amount”字段,它是一个计算字段(来自发票项目的“amount”的总和)。
我想在创建或更新发票时计算此金额。我正在尝试在发票模型的before_save事件中执行此操作。下面的代码几乎起作用,但保存的总数始终落后一步。也就是说,如果我有一张总额为20美元的发票,并将此发票的发票项目更改为总额为15美元,则保存我的发票后,总额不会更改。如果我打开同一张发票,然后再次保存它,总额将正确更新。
我假设我下面计算总和的那行代码正在访问已经保存在数据库中的行项目,而不是那些刚刚更改并即将保存的项目。但我不知道如何访问它们。
class Invoice < ActiveRecord::Base
  has_many :invoice_items, :dependent => :destroy

  accepts_nested_attributes_for :invoice_items, :allow_destroy => true 

  before_save :record_total_amount

  private
    def record_total_amount
      self.total_amount = self.invoice_items.sum('amount')
    end
end

非常感谢您的帮助。


总金额需要保存吗?您可以将其定义为实例方法,每次请求时重新计算它。 - dunedain289
我为了性能原因而保存它。 - Joel Friedlaender
2个回答

5

我解决了这个问题,我需要用以下代码替换计算行:

self.total_amount = invoice_items.map(&:amount).sum

4
尝试这个: self.total_amount = invoice_items.reject(&:marked_for_destruction?).map(&:amount).sum 这行代码的作用是计算发票条目中在被标记为删除之外的所有金额之和。

你也可以直接使用 .sum 替换 .mapself.total_amount = invoice_items.reject(&:marked_for_destruction?).sum(&:amount) - Donny Kurnia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接