バリデーション uniqueness
ブックマーク機能を作る際、unique制約が必要だったので理解を深めるためにまとめます!
なぜunique制約が必要なのか
ブックマーク機能は、どのユーザーが、どの掲示板をブックマークしたという関係性を保存することです。
解除する際は保存したデータを消す必要があり、データが重複していると消したはずなのに同じデータが残ってしまうことがあり、一意性が失われてしまいます。
uniquenessとは
このヘルパーは、オブジェクトが保存される直前に、属性の値が一意(unique)であり重複していないことを検証する。
class Bookmark < ApplicationRecord validates :user_id, uniqueness: true end
上記のコードだと、1ユーザーに対して1つしかブックマークできないようになっています。このままでは作りたい要件とは異なってしまいます。
そこでscope
を使用します。
scope
とはuniqueness
に用意されているオプションで、範囲を指定して、一意かどうかをチェックしてくれます。
class Bookmark < ApplicationRecord validates :user_id, uniqueness: { scope: :board_id } end
上記のコードは、1ユーザーが1掲示板に1ブックマークという範囲を指定しています。
:scopeを用いる一意性バリデーションの違反を防止する目的でデータベース側に制約を作成したい場合は、データベース側で両方のカラムにuniqueインデックスを作成しなければなりません。
class CreateBookmarks < ActiveRecord::Migration[5.2] def change create_table :bookmarks do |t| t.references :user, foreign_key: true t.references :board, foreign_key: true t.timestamps end add_index :bookmarks, [:user_id, :board_id], unique: true end end