2010-02-25 29 views
3

我試圖不打擊這裏的默認值,並使用Rails嵌入屬性的支持(來自http://ryandaigle.com/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes)。我用標籤標記東西,所有作品都會膨脹,並且對於每件事情我都有一個嵌套字段的表單,通過名稱創建一個新標籤。麻煩的是,我需要確保每個標籤都有唯一的名稱。如果用戶輸入已存在的名稱,而不是創建新的標籤,那麼我需要創建與該已有標籤關聯的關聯。我該怎麼做呢?以嵌套形式實現唯一性約束

回答

1

可能有更好的方法來做到這一點,但這是關於我現在可以提出的最好的方法。

在has_many(:through)關聯中,accepts_nested_arguments_for使用對虛擬屬性#{association}_attributes的分配來發揮其魔力。它需要一個哈希數組,每個哈希包含屬性鍵及其值。帶有id的任何散列將被更新(或者如果:_delete鍵的值爲true,則被刪除)。缺少id的任何散列將被用於創建該關聯的新項目。所以關鍵是要調用攔截tags_associations=和檢查任何缺失IDS具有相同名稱值現有標籤的哈希,並與tags_attributes將用來執行該協會現有標籤的項替換它。 N.B.對於has_one和belongs_to關係, tag_attributes將期望單個散列。代碼將類似,但更簡單。

class Thing < ActiveRecord::Base 
    has_many :tags, :through => :taggings 
    has_many :taggings 
    accepts_nested_attributes_for :tags 

    def tags_attributes_with_recycling=(attributes) 
    existing_attributes = attributes.reject{|attribute| attribute[:id].nil?} 
    new_attributes = attributes - existing_attributes 
    new_and_recycled_attributes = new_attributes.map { |attribute| 
     tag_id = Tag.find_by_name(attribute[:name]).id 
     tag_id ? {:id => tag_id) : attribute 
    } 
    tags_attributes_without_recycling= (existing_attributes + new_and_recycled_attributes) 
    end 

    alias_method_chain :tags_attributes=, :recycling 
end 

這是未經測試,所以不能保證。但它至少應該讓你跟蹤解決方案。

1

在你的事類,定義一個tags_attributes =方法覆蓋默認並使用Tag.find_or_create

def tags_attributes=(attributes) 
    attributes.each do |attr| 
    Tag.find_or_create_by_name(attr[:name]) 
    end 
end 

不知道是什麼屬性的哈希看起來像,但你的想法。