Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby on Rails - nested attributes: How do I access the parent model from child model

I have a couple of models like so

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

The above validation so obviously doesn't work because when I'm reading the bill_items from nested attributes inside the bill form, the attributes bill_item.bill_id or bill_item.bill are not available before being saved.

So how do I go about doing something like that?

like image 820
TMaYaD Avatar asked Apr 09 '10 22:04

TMaYaD


3 Answers

I "fixed" it by setting parent in a callback:

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

The set_nest method did the trick. Wish it came standard with accepts_nested_attributes_for.

like image 112
TMaYaD Avatar answered Oct 20 '22 14:10

TMaYaD


In Rails 4 (didn't test on earlier versions) you can access the parent model by setting the inverse_of option on has_many or has_one:

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

  accepts_nested_attributes_for :bill_items
end

Documentation: Bi-directional associations

like image 43
yenshirak Avatar answered Oct 20 '22 15:10

yenshirak


The bill_item.bill should be available , you could try to do a raise self.bill.inspect to see if it's there or not, but i think the problem is elsewhere.

like image 1
dombesz Avatar answered Oct 20 '22 15:10

dombesz