こんにちは。
rails初学者です。
自分用備忘録のために、記事をまとめます。
「特定の2つ以上のカラムの組み合わせを、重複登録できないようにする」というテーマです。
やりたいこと
特定の2つ以上のカラムの組み合わせを、重複登録できないようにする。
例:
同じユーザーが同じ商品に複数レビューしない
同じ生徒が同じ授業に二重登録しない
モデル側でバリデーションを追加
Railsのモデルで「この組み合わせは重複させないよ」とルールを決める。
class Enrollment < ApplicationRecord
belongs_to :student
belongs_to :course
# 同じ生徒が同じ授業に重複登録できないようにする
validates :student_id, uniqueness: {
scope: :course_id,
message: "はこの授業にすでに登録されています"
}
end
データベースにユニーク制約を追加
① マイグレーション作成
アプリ側のバリデーションだけだと、同時に複数の人が操作したときなどにミスが起こる可能性があるため、DBでも絶対に重複が入らないようにガードしておく。
bin/rails generate migration add_unique_index_to_enrollments
②マイグレーションファイルを編集
class AddUniqueIndexToEnrollments < ActiveRecord::Migration[8.0]
def change
add_index :enrollments, [:student_id, :course_id], unique: true
end
end
③実行
bin/rails db:migrate
すでに重複データがないか確認する
重複していたら、マイグレーションでエラーになる。
Railsコンソールで確認する。
bin/rails console
Enrollment
.group(:student_id, :course_id)
.having("COUNT(*) > 1")
.count
結果が {} ならOK
まとめ
対策場所 | 目的 |
---|---|
モデル | エラーメッセージで教えてあげる |
DB | 絶対に重複を防ぐ最後の砦 |
バリデーションとユニーク制約の違い
比較 | モデルのバリデーション | DBのユニーク制約 |
---|---|---|
目的 | ユーザーに優しく教える | データの正しさを守る |
実行のタイミング | アプリが保存しようとしたとき | データベースに保存するとき |
初学者のため、間違えていたらすいません。