我试图不在这里对抗默认值并使用Rails内置支持嵌套属性(来自http://ryandaigle.com/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes)。我用标签标记了东西,并且所有作品都膨胀了,对于每个东西我都有一个带有嵌套字段的表单,它通过名称创建一个新的标签。麻烦的是,我需要确保每个标签都有一个唯一的名称。如果用户输入已存在的名称,我需要创建与该预先存在的标签的关联,而不是创建新标签。我该怎么做?
答案 0 :(得分:1)
这可能是一种更好的方法,但这是我现在能想到的最好的方法。
在has_many(:through)关联中,accepts_nested_arguments_for使用对虚拟属性#{association}_attributes
的赋值来实现其魔力。它需要一个哈希数组,其中每个哈希都包含属性键及其值。任何具有id的哈希都将被更新(如果存在值为true的:_delete
键,则会被删除)。任何缺少id的哈希都将用于创建该关联的新项目。因此,关键是截取对tags_associations=
的调用,并检查具有相同名称值的现有标记缺少id的任何哈希值,并将其替换为tags_attributes将用于与之关联的条目。现有标签。对于has_one和belongs_to关系 N.B。,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 :(得分:1)
在你的Thing类中,定义一个tags_attributes =方法来覆盖默认值并使用Tag.find_or_create
def tags_attributes=(attributes)
attributes.each do |attr|
Tag.find_or_create_by_name(attr[:name])
end
end
不确定属性hash会是什么样子但你明白了。