Ruby on Rails ActiveRecord“has_many:through”唯一性验证

时间:2011-02-26 20:58:00

标签: ruby-on-rails activerecord

目前我每次检查都会插入一个新的关系,如果它不存在:

unless Relationship.exists?(:entry_id => entry.id, :tag_id => tag.id)

如何在关系模型中实现此类验证,以便它不允许在同一条目和标记之间建立多个关系?

2 个答案:

答案 0 :(得分:21)

class Relationship < ActiveRecord::Base
  belongs_to :entry
  belongs_to :tag
  validates :tag_id, :uniqueness => { :scope => :entry_id }
end

答案 1 :(得分:8)

假设您的模型看起来像这样:

class Entry < ActiveRecord::Base
  has_many :relationships
  has_many :tags, :through => :relationships
end

class Tag < ActiveRecord::Base
  has_many :relationships
  has_many :entries, :through => :relationships
end

class Relationship < ActiveRecord::Base
  belongs_to :entry
  belongs_to :tag
end

您可以为Relationship加入模型添加唯一的验证:

validates_uniqueness_of :tag_id, :scope => :entry_id

validates_uniqueness_of方法将确保关系不存在,:scope选项将匹配范围限定为给定列。 rails通过此验证生成的SQL将如下所示:

SELECT `relationships`.id
FROM `relationships`
WHERE (`relationships`.`tag_id` = <tag id> AND `relationships`.`entry_id` = <entry id>)
LIMIT 1

(您会注意到它与您明确使用Relationship.exists?(:entry_id => entry.id, :tag_id => tag.id)生成的SQL基本相同),如果找到记录,验证将失败。

同样,与您要验证唯一性的任何情况一样,请确保tag_id, entry_id表中的relationships上有唯一键。有关详细信息,请参阅上面链接的API页面的this article和“并发性和完整性”。