ぺんぎんのRails日記

ぺんぎん。エンジニア経験ゼロ。Rails勉強中。

【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のインデックスにもユニーク制約をつけることができました。

完成です☆

参考サイト

310nae.com

note.com