views:

485

answers:

2

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?

A: 

Yeah, this kind of problem can be annoying. You could try adding a virtual attribute to your Bill Item model like this:

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

And then in your view you could add a hidden field like this:

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

This hasn't been test but it might work. You might not find it desirable to have the store_id in the html but it may not be a concern. Let me know if this helps.

CalebHC
+1  A: 

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.

dombesz
Even if it isn't available, the OP could just add a before_validation callback to set it. The BillItems shouldn't need to know their own IDs or the parent Bill's ID to validate.
hornairs