1

我是Rails的新手。今天遇到了保存关联模型的问题。

我有 2 个具有以下关联的模型,标签模型对属性“名称”具有唯一性的验证角色。

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 表中的关联。

4

1 回答 1

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那里的方法。

于 2013-04-27T19:14:29.213 回答