2010-11-12 80 views
14

我有以下型號accepts_nested_attributes_for就鏈接到現有記錄,而不是創建一個新的

class Order < AR::Base 
    has_many :products 

    accepts_nested_attributes_for :products 
end 

class Product < AR::Base 
    belongs_to :order 
    has_and_belongs_to_many :stores 

    accepts_nested_attributes_for :stores 
end 

class Store < AR::Base 
    has_and_belongs_to_many :products 
end 

現在我有一個順序圖,其中我想更新該產品的商店。 問題是我只想將產品連接到我的數據庫中的現有商店,而不是創建新的商店。

我在訂單視圖形式如下(使用Formtastic):

= semantic_form_for @order do |f| 
    = f.inputs :for => :live_products do |live_products_form| 
    = live_products_form.inputs :for => :stores do |stores_form| 
     = stores_form.input :name, :as => :select, :collection => Store.all.map(&:name) 

雖然它的嵌套它工作正常。 問題是,當我選擇商店並嘗試更新訂單(以及產品和商店)時,Rails嘗試使用該名稱創建新商店。我希望它只使用現有的商店並將產品連接到該商店。

任何幫助表示讚賞!

編輯1:

在我以一種非常粗暴的方式解決了這個問題到底:

# ProductsController 

def update 
    [...] 

    # Filter out stores 
    stores_attributes = params[:product].delete(:stores_attributes) 

    @product.attributes = params[:product] 

    if stores_attributes.present? 
    # Set stores 
    @product.stores = stores_attributes.map do |store_attributes| 
     # This will raise RecordNotFound exception if a store with that name doesn't exist 
     Store.find_by_name!(store_attributes[:name]) 
    end 
    end 

    @order.save 

    [...] 
end 

編輯2:

Pablo的解決方案更優雅,應該優先於雷。

+0

審查a_n_a_f(http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html)我第一次興奮,當我看到update_only選項,但很快就意識到了文檔後,有沒有辦法做我想做的事(update_only在創建新對象之前更新現有對象)。 – 2010-11-23 20:13:42

回答

21

試圖實現一個:reject_if是檢查商店已經存在,然後使用它:

class Product < AR::Base 
    belongs_to :order 
    has_and_belongs_to_many :stores 

    accepts_nested_attributes_for :stores, :reject_if => :check_store 

    protected 

    def check_store(store_attr) 
     if _store = Store.find(store_attr['id']) 
     self.store = _store 
     return true 
     end 
     return false 
    end 
end 

我有這樣的代碼在當前項目工作的罰款。

請讓我知道你是否找到了更好的解決方案。

+0

非常聰明!我以一種不太優雅的方式解決了這個問題(我將編輯我的問題來展示它),但是您的解決方案應該更好。 – 2011-05-06 10:04:36

+8

這對我來說沒有意義。 'check_store'中的'self'是產品...並且產品沒有'商店'關係(它是HABTM:商店)。那麼這段代碼實際上做了什麼?另外,它似乎沒有更新找到的商店。 – davemyron 2011-06-15 20:57:59

+0

我通過查找現有的相關記錄並更新其在reject_if *中的屬性*來調整它以供我自己使用。當然,這看起來很拙劣,但是很有效。 – davemyron 2011-06-15 21:20:43

0

我有同樣的問題,並通過將ID添加到嵌套的參數列表來解決它。

def family_params 
    params.require(:family).permit(:user_id, :address, people_attributes: [:id, :relation, :first_name, :last_name) 
end 
+0

早在Strong Parameters出來之前,我就寫了我的問題。 – 2016-03-14 07:32:12

相關問題