2012-03-15 250 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))