我有几个这样的模型
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
上述验证显然不起作用,因为当我从账单表单中的嵌套属性中读取bill_items时,属性bill_item.bill_id或bill_item.bill在保存之前不可用。
那我该怎么做呢?
答案 0 :(得分:18)
这就是我最终解决的问题;通过在回调中设置父级
has_many :bill_items, :before_add => :set_nest
private
def set_nest(bill_item)
bill_item.bill ||= self
end
答案 1 :(得分:8)
在Rails 4中(未在早期版本上测试),您可以通过在inverse_of
或has_many
上设置has_one
选项来访问父模型:
class Bill < ActiveRecord::Base
has_many :bill_items, inverse_of: :bill
belongs_to :store
accepts_nested_attributes_for :bill_items
end
答案 2 :(得分:1)
bill_item.bill应该可用,您可以尝试提升self.bill.inspect以查看它是否存在,但我认为问题出在其他地方。
答案 3 :(得分:1)
我通过在回调中设置父级来“修复”它:
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
set_nest方法成功了。希望它标准化为accepts_nested_attributes_for。
答案 4 :(得分:0)
是的,这种问题可能很烦人。您可以尝试将虚拟属性添加到Bill Item模型中,如下所示:
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
然后在您的视图中,您可以添加如下隐藏字段:
<%= bill_item.hidden_field :store_id, :value => store_id %>
这尚未经过测试,但可能有效。你可能不会觉得在html中使用store_id是可取的,但它可能不是一个问题。如果这有帮助,请告诉我。