2010-04-09 99 views
20

访问父模型我有像这样Ruby on Rails的 - 嵌套的属性:我如何从子模型

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

我解决了这个加入电话回联想,:before_add =>:set_nest – TMaYaD 2011-02-19 06:35:40

回答

18

这是我如何解决它最终;通过回调

has_many :bill_items, :before_add => :set_nest 

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

是啊!它最近一直在窃听我。我希望它是自动的,如果回叫函数是针对关联代理(如关联扩展)而不是关联所有者运行的,则可以编写更通用的版本。 – ilpoldo 2011-03-24 18:22:34

0

是啊,这种问题可以是恼人。你可以尝试添加一个虚拟属性到您的帐单项目模型是这样的:

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,但它可能不是问题。让我知道这是否有帮助。

1

的bill_item.bill应该可以,你可以尝试做加薪self.bill.inspect,看看它的存在与否,但我认为这个问题是在其他地方。

+0

就算是不可用,则可能OP只需添加一个before_validation回调来设置。 BillItems不需要知道他们自己的ID或父母Bill的ID来验证。 – hornairs 2010-05-12 13:51:05

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方法奏效了。希望它的标准与accep_nested_attributes_for。

7

设置父在Rails 4(没有测试早期版本),你可以通过设置在has_manyhas_oneinverse_of选项访问父模型:

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

    accepts_nested_attributes_for :bill_items 
end 

文档:Bi-directional associations

+0

对于导轨4,这是真实的答案 – Abs 2016-02-07 03:47:46