2011-02-28 66 views
7

我有一个发票模型,即“有许多”发票项目。我有一个表单,允许您创建/编辑发票,并且此表单接受发票项目的嵌套属性。Ruby on Rails - before_save计算在acceptable_nested_attributes_for

在我的发票模型中,有一个“total_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 

任何帮助将不胜感激。

+0

是否必须保存total_amount?只要将其定义为实例方法,您就可以重新计算它。 – dunedain289 2011-02-28 06:49:45

+0

由于性能原因我正在保存它 – 2011-03-18 01:18:42

回答

5

我解决了这个问题,我不得不更换这一个计算行:

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

试试这个:

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

+0

您也可以直接用'.sum'替换'.map': 'self.total_amount = invoice_items.reject(&:marked_for_destruction?)。sum(&:amount)' – 2017-03-13 08:52:58

0

我知道这是有点晚了,但也许有人能效益。检查日志以查看数据库操作的顺序。我有一个类似的问题,在导致类似结果的父模型的保存操作之后插入嵌套模型。