我是铁路的新手。今天我遇到了保存相关模型的问题。
我有两个具有以下关联的模型,Tag模型具有属性'name'的验证角色,是唯一性。
class Product < ActiveRecord::Base
has_and_belongs_to_many :tags
validates_associated :tags
end
class Tag < ActiveRecord::Base
has_and_belongs_to_many :products
validates :name, :presence => true, :uniqueness => true
end
我要归档的是创建一个与多个标签关联的产品对象。我使用了以下功能:
def self.create_with_tags(value)
tags = []
if value.has_key? :tags
tags = value[:tags]
value.delete :tags
end
p = Product.new(value)
tags.each do |tag|
p.tags.build(:name => tag)
end
p.save!
p
end
测试代码是
p = Product.create_with_tags(:name => 'test product', :status => true, :tags =>['tag1','tag2','tag3','tag4'])
当数据库中不存在标签名称['tag1','tag2','tag3','tag4']时,测试代码正常工作; 如果其中一个标记已存在于数据库中,例如“tag1”,则关联验证将失败,整个创建过程将回滚。
我要归档的是:如果数据库中已存在某些标记,则验证不会失败,而是找到(但不创建)现有标记,并创建产品与现有标记之间的关联。例如,如果'tag1'已经在数据库中,则不会再次创建它,但会创建products_tags表中的关联。
答案 0 :(得分:0)
我建议将结构与现有结构略有不同:我不是使用类方法作为替代构造方法,而是使用标准Product.new
方法作为入口点,并传递Tag实例它作为标准属性。那怎么样:
tag_ids = ['tag1','tag2','tag3','tag4'].map do |t|
Tag.where(:name => t).first_or_create.id
end
p = Product(:name => 'test product', :status => true, :tag_ids => tag_ids)
使用first_or_create
,您可以先检查具有给定名称的Tag是否已存在,如果不存在则创建一个,最后使用内置的Product.new
方法而不是使用单独的构造方法(例如你的self.create_with_tags
方法。
如果您真的想继续使用self.create_with_tags
方法,那么您仍然可以使用first_or_create
方法。