Currently I insert a new relationship by everytime ch开发者_如何转开发ecking, if it doesn't exist:
unless Relationship.exists?(:entry_id => entry.id, :tag_id => tag.id)
How could I implement such validation inside the Relationship model, so that it wouldn't allow to have more than one relationship between the same entry and tag?
class Relationship < ActiveRecord::Base
belongs_to :entry
belongs_to :tag
validates :tag_id, :uniqueness => { :scope => :entry_id }
end
Assuming your models look something like this:
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
You could add a unique validation to your Relationship
join model:
validates_uniqueness_of :tag_id, :scope => :entry_id
The validates_uniqueness_of
method will ensure that the Relationship doesn't already exist, and the :scope
option will scope the match to the given column. The SQL generated by rails via this validation will look like:
SELECT `relationships`.id
FROM `relationships`
WHERE (`relationships`.`tag_id` = <tag id> AND `relationships`.`entry_id` = <entry id>)
LIMIT 1
(which you'll notice is essentially the same SQL generated by your explicit use of Relationship.exists?(:entry_id => entry.id, :tag_id => tag.id)
), and if a record is found, validation will fail.
As well, as with any case where you want to validate uniqueness, ensure that you have a unique key on tag_id, entry_id
in your relationships
table. See this article and the "Concurrency and integrity" of the API page I linked above for more info.
精彩评论