Ответ 1
Вы можете добавить уникальность для соединения таблицы
add_index :users_roles, [ :user_id, :role_id ], :unique => true, :name => 'by_user_and_role'
см. В таблице соединений, какой лучший способ обхода Rails отсутствует составной ключ?
В вашей базе данных будет создано исключение, которое вы должны обработать.
Я не знаю, какая готовая для использования проверка рельсов для этого случая, но вы можете добавить свою собственную проверку следующим образом:
class User < ActiveRecord::Base
has_and_belongs_to_many :roles, :before_add => :validates_role
Я просто молча удалю вызов базы данных и сообщит об успешном завершении.
def validates_role(role)
raise ActiveRecord::Rollback if self.roles.include? role
end
ActiveRecord:: Rollback внутренне захвачен, но не ререйзирован.
Изменить
Не используйте ту часть, где я добавляю пользовательскую проверку. Это работает, но есть лучшие альтернативы.
Используйте опцию :uniq
для ассоциации в качестве @Spyros, предложенную в другом ответе:
class Parts < ActiveRecord::Base
has_and_belongs_to_many :assemblies, :uniq => true, :read_only => true
end
(этот фрагмент кода из Rails Guides v.3). Читайте на Rails Guides v 3.2.13 ищите 4.4.2.19: uniq
Руководство Rails v.4 специально предупреждает об использовании include?
для проверки уникальности из-за возможных условий гонки.
Часть добавления индекса для соединения с таблицей остается.