2010-04-09 23 views
20

que tiene un par de modelos como talRuby on Rails - atributos anidados: ¿Cómo accedo al modelo padre del niño modelo

class Bill < ActiveRecord::Base 
    has_many :bill_items 
    belongs_to :store 

    accepts_nested_attributes_for :bill_items 
end 

class BillItem <ActiveRecord::Base 
    belongs_to :product 
    belongs_to :bill 

    validate :has_enough_stock 

    def has_enough_stock 
    stock_available = Inventory.product_is(self.product).store_is(self.bill.store).one.quantity 
    errors.add(:quantity, "only #{stock_available} is available") if stock_available < self.quantity 
    end 
end 

La validación por encima de lo que, obviamente, no funciona porque cuando estoy leyendo bill_items de atributos anidados dentro del formulario de factura, los atributos bill_item.bill_id o bill_item.bill no están disponibles antes de ser guardados.

Entonces, ¿cómo hago para hacer algo como eso?

+0

he resuelto esto añadiendo una llamada a la asociación,: before_add =>: set_nest – TMaYaD

Respuesta

18

Así es como lo resolví eventualmente; mediante el establecimiento de los padres en la devolución de llamada

has_many :bill_items, :before_add => :set_nest 

private 
    def set_nest(bill_item) 
    bill_item.bill ||= self 
    end 
+1

¡Sí! Me ha estado molestando últimamente. Ojalá fuera automático, se podría escribir una versión más genérica si las funciones de devolución de llamada se ejecutaran contra el proxy de asociación (como las extensiones de asociación) en lugar del propietario de la asociación. – ilpoldo

0

Sí, este tipo de problema puede ser molesto. Usted podría intentar agregar un atributo virtual para su modelo de artículo de Bill como esto:

class BillItem <ActiveRecord::Base 
    belongs_to :product 
    belongs_to :bill 

    attr_accessible :store_id 

    validate :has_enough_stock 

    def has_enough_stock 
    stock_available = Inventory.product_is(self.product).store_is(load_bill_store).one.quantity 
    errors.add(:quantity, "only #{stock_available} is available") if stock_available < self.quantity 
    end 

    private 

    def load_bill_store 
    Store.find_by_id(self.store_id) 
    end 
end 

Y a continuación, en su opinión, se podría añadir un campo oculto de esta manera:

<%= bill_item.hidden_field :store_id, :value => store_id %> 

Esto no ha sido prueba, pero podría funcionar. Puede que no le convenga tener el store_id en el html, pero puede que no sea una preocupación. Déjeme saber si esto ayuda.

1

El bill_item.bill debe estar disponible, puede tratar de hacer un aumento self.bill.inspect para ver si está allí o no, pero creo que el problema está en otra parte.

+0

Incluso si no está disponible, el OP sólo pudiera añadir una devolución before_validation para configurarlo. Los BillItems no deberían necesitar conocer sus propias identificaciones o la identificación de Bill padre para validar. – hornairs

1

que "fija" mediante el establecimiento de los padres en una devolución de llamada:

class Bill < ActiveRecord::Base 
    has_many :bill_items, :dependent => :destroy, :before_add => :set_nest 
    belongs_to :store 

    accepts_nested_attributes_for :bill_items 

    def set_nest(item) 
    item.bill ||= self 
    end 
end 

class BillItem <ActiveRecord::Base 
    belongs_to :product 
    belongs_to :bill 

    validate :has_enough_stock 

    def has_enough_stock 
     stock_available = Inventory.product_is(self.product).store_is(self.bill.store).one.quantity 
    errors.add(:quantity, "only #{stock_available} is available") if stock_available < self.quantity 
    end 
end 

El método set_nest hizo el truco. Desearía que venga de serie con accepts_nested_attributes_for.

7

En Rails 4 (no probar en versiones anteriores) se puede acceder al modelo padre estableciendo la opción inverse_of en has_many o has_one:

class Bill < ActiveRecord::Base 
    has_many :bill_items, inverse_of: :bill 
    belongs_to :store 

    accepts_nested_attributes_for :bill_items 
end 

Documentación: Bi-directional associations

+0

Esta es la verdadera respuesta para los rieles 4 – Abs

Cuestiones relacionadas