2012-03-15 256 views
9

Ruby on Rails has_many通过关联对象保存到数据库之前,我试图访问ActiveRecord上的关联对象。在Ruby on Rails项目中保存

class Purchase < ActiveRecord::Base 

    has_many :purchase_items, dependent: :destroy 
    has_many :items, through: :purchase_items 

    validate :item_validation 

    def item_ids=(ids) 
    ids.each do |item_id| 
     purchase_items.build(item_id: item_id) 
    end 
    end 

    private 

    def item_validation 
    items.each do |item| 
     ## Lookup something with the item 
     if item.check_something 
     errors.add :base, "Error message" 
     end 
    end 
    end 

end 

如果我建立了我的对象,像这样: purchase = Purchase.new(item_ids: [1, 2, 3]),并尝试将其保存到item_validation方法不具备的项目集合填充呢,所以尽管项目已经设置设置它没有得到一个有机会致电check_something方法。

是否有可能在我的购买模型和关联模型持续存在之前访问商品集合,以便我可以针对它们运行验证?

如果我改变我的item_validation方法是:

def item_validation 
    purchase_items.each do |purchase_item| 
    item = purchase_item.item 
    ## Lookup something with the item 
    if item.something 
     errors.add :base, "Error message" 
    end 
    end 
end 

它似乎工作我希望它的方式,但我觉得很难相信,有没有办法与直接访问的项目集合我购买之前的导轨以及相关记录将保存到数据库中。

回答

0

您是否有文件显示purchase = Purchase.new(item_ids: [1, 2, 3])做了什么?

对我来说,你只是将非数据库属性'item_ids'设置为一个数组(即不创建关联)。

你的购买模式甚至不应该有任何外键列直接设置。相反,purchase_items表中有purchase_iditem_id的条目。要创建购买和三个项目之间的链接,您需要在joiner表中创建三个条目。

,如果你只是这样做,而不是?:

purchase = Purchase.new 
purchase.items = Item.find([1,2,3]) 
1

尝试添加参数inverse_of:在的has_many和belongs_to的定义。该inverse_of争论它是在其他模型中的关系的名称,例如:

class Post < ActiveRecord::Base 
    has_many :comments, inverse_of: :post 
end 

class Comment < ActiveRecord::Base 
    belongs_to :post, inverse_of: :comments 
end 

不要忘了还加它的其他类,如购买项目和项目

希望它可以帮助

1

删除自己的item_ids=方法 - 导轨为您生成一个(请参阅collection_singular_ids=ids)。这可能已经解决了你的问题。

class Purchase < ActiveRecord::Base 

    has_many :purchase_items, dependent: :destroy 
    has_many :items, through: :purchase_items 

    validate :item_validation 

    private 

    def item_validation 
    items.each do |item| 
     ## Lookup something with the item 
     if item.check_something 
     errors.add :base, "Error message" 
     end 
    end 
    end 

end 

附带在我的脑海里看着你的代码的第二件事:将验证到Item类。所以:

class Purchase < ActiveRecord::Base 
    has_many :purchase_items, dependent: :destroy 
    has_many :items, through: :purchase_items 
end 

class Item < ActiveRecord::Base 
    has_many :purchase_items 
    has_many :purchases, through: :purchase_items 

    validate :item_validation 

    private 

    def item_validation 
     if check_something 
     errors.add :base, "Error message" 
     end 
    end 
end 

Purchase记录也将是无效的,如果Item S的一个是无效的。

0

我假设你不能访问它们,因为在记录保存之前的id不可用。但正如你提到你有机会获得第一级协会purchase_items,这样你就可以提取所有的ID,并通过他们在whereItem

items = Item.where(purchase_item_id: purchase_items.map(&:id))