結合テーブルに一意性を追加できます
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
include?
Rails Guide v.4 では、競合状態の可能性があるため、一意性のチェックに 使用しないように特に警告しています。
結合テーブルへのインデックスの追加に関する部分は残ります。