您可以为连接表添加唯一性
add_index :users_roles, [ :user_id, :role_id ], :unique => true, :name => 'by_user_and_role'
请参阅在连接表中,Rails 缺少复合键的最佳解决方法是什么?
然后,您的数据库将引发异常,您必须处理该异常。
我不知道任何准备好在这种情况下使用 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 Guide v.4 特别警告不要使用include?
for 检查唯一性,因为可能存在竞争条件。
关于添加索引以连接表的部分仍然存在。