2011-02-26 125 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