Ответ 1
class Relationship < ActiveRecord::Base
belongs_to :entry
belongs_to :tag
validates :tag_id, :uniqueness => { :scope => :entry_id }
end
В настоящее время я вставляю новое отношение, проверяя каждый раз, если оно не существует:
unless Relationship.exists?(:entry_id => entry.id, :tag_id => tag.id)
Как я могу реализовать такую проверку внутри модели отношений, чтобы она не позволяла иметь более одной связи между одной и той же записью и тегом?
class Relationship < ActiveRecord::Base
belongs_to :entry
belongs_to :tag
validates :tag_id, :uniqueness => { :scope => :entry_id }
end
Предполагая, что ваши модели выглядят примерно так:
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
(который вы заметите, по сути, тот же SQL, сгенерированный явным использованием Relationship.exists?(:entry_id => entry.id, :tag_id => tag.id)
), и если запись найдена, проверка не будет выполнена.
Также, как и в любом случае, когда вы хотите проверить уникальность, убедитесь, что у вас есть уникальный ключ на tag_id, entry_id
в вашей таблице relationships
. См. эту статью и "Concurrency и целостность" страницы API, с которой я связан выше, для получения дополнительной информации.