2011-02-26 132 views

回答

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

假设你的模型看起来是这样的:

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选项将把匹配范围限定到给定列。通过此验证通过轨道生成的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),如果一个记录被发现,验证将失败。

同样,如果您想验证唯一性,请确保您在relationships表中的tag_id, entry_id上有唯一密钥。请参阅this article以及上面链接的API页面的“并发性和完整性”以获取更多信息。

+0

谢谢,但我如何添加唯一键,我仍然可以有相同的tag_id为其他条​​目和许多不同的标签为同一条目? add_index“relationships”,[“tag_id”],:unique => true - 我想会阻止我多次使用相同的tag_id。 – krn 2011-02-26 21:32:15

+1

您必须为* both *列创建索引。在迁移中,它看起来像“add_index:relationships,[:tag_id,:entry_id],:unique => true'。然后,执行DBMS,如果两列的值与现有行匹配,则新行只有冲突。 – 2011-02-26 21:34:09

+0

(这应该是*你的DBMS) – 2011-02-26 21:39:41

相关问题