【rails】バリデーションで同じデータが重複しないようにする【uniqueness】
uniqueness
テーブル内で同じデータが重複しないようにするには、uniqueness: trueを使ってユニーク制約をつけます。
たとえば、同じ名前のユーザーが登録できないようにするには、Userモデルで以下のようにバリデーションを設定します。
user.rb
validates :name, uniqueness: true
これでnameカラムに同じ値が入らないように設定できました。
では、同じユーザー名は存在できるけれど、同じユーザー名、且つ、同じメールアドレスのユーザーが重複しないようにするにはどうしたらいいでしょうか?
validates :name, uniqueness: true validates :email, uniqueness: true
これだと、nameカラムとemailカラムで別々に検証されるため、同じユーザー名も同じメールアドレスも存在できないことになってしまいます。
このように同時に2つのカラムが絡んだユニーク制約をかけたいときは以下のようにします。
scopeオプションで複数カラムにユニーク制約をかける
uniquenessはオプションでscopeを追加して、検証する範囲を指定することができます。
validates :カラム名1, uniqueness: { scope: :カラム名2 }
"scope"とは英語で「範囲」という意味なので、scopeオプションでユニーク制約をつけると、「カラム2の範囲内でカラム1の値が重複しないようにする」という意味になりますね!
前述のように、同じユーザー名且つ、同じメールアドレスが重複しないようにするには、以下のようにします。
user.rb
validates :name, uniqueness: { scope: :email }
これで同じユーザー名かつ同じメールアドレスの値は重複できなくなりました。
マイグレーションにもユニーク制約をつけるのを忘れずに!
わたしはこれを忘れてユニーク制約が動かなかったので、忘れずにこちらもつけましょう!
class CreateUsers < ActiveRecord::Migration[5.2] add_index :users, [:name, :email], unique: true
これでDBのインデックスにもユニーク制約をつけることができました。
完成です☆