2011-02-28 8 views
7

tengo un modelo de factura, que "tiene muchas" posiciones de factura. Tengo un formulario que le permite crear/editar una factura, y este formulario acepta atributos anidados para los artículos de la factura.Ruby on Rails - cálculo before_save en accepts_nested_attributes_for

En mi modelo de factura, hay un campo "TOTAL_AMOUNT" que es un campo calculado (la suma de "cantidad" de las posiciones de factura).

quiero para calcular esta cantidad cuando se crea una factura, o actualizada. Estoy intentando hacer esto en el evento before_save de mi modelo de factura. El siguiente código casi funciona, sin embargo, el total que se guarda está siempre un paso atrás. Es decir. si tengo una factura con un total de $ 20, y edito esta factura y cambio los artículos de la factura para un total de $ 15, entonces guardo mi factura, el total no cambia. Si abro la misma factura y la vuelvo a guardar, el total se actualiza correctamente.

Asumo que mi línea de abajo que calcula la suma está accediendo a los elementos de línea que se guardan en la base de datos ya, y no los que acaban de ser cambiado y están a punto de ser salvado. Sin embargo, no sé cómo acceder a ellos.

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 

Cualquier ayuda sería muy apreciada.

+0

¿Tiene que guardarse total_amount? Puede recalcularlo cuando lo solicite definiéndolo como un método de instancia. – dunedain289

+0

estoy guardando para razones de rendimiento –

Respuesta

5

He resuelto este problema, tuve que reemplazar la línea de cálculo con éste:

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

Prueba esto:

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

+0

También puede reemplazar '' .map' con .sum' directamente: 'self.total_amount = invoice_items.reject. (Y:? Marked_for_destruction) suma (Y: cantidad)' –

0

Sé que es un poco tarde, pero tal vez alguien pueda beneficio. Verifique los registros para ver el orden de las operaciones de db. Tuve un problema similar en el que la inserción de modelos anidados se realizó después de la operación de guardado del modelo principal que dio como resultado resultados similares.