🍣
ユニークのvalidatesって必要?
Railsアプリケーションを開発しているとき、
- データのユニーク制約ってDBだけにつけておけばいいの?
- それともvalidatesもつけといた方がいい??
どっちなの?ってなった
問題になったテーブル
※ブログ用に色々改変
# == Schema Information
#
# Indexes
#
# index_user_item_ratings_on_item_id (item_id)
# index_user_item_ratings_on_user_id (user_id)
# index_user_item_ratings_on_user_id_and_item_id UNIQUE (user_id, item_id)
#
class UserItemRating < ApplicationRecord
belongs_to :user
belongs_to :item
enum rating: {
bad: 0,
good: 1,
very_good: 2
}
# こいつがいるのかいらないのか
validates :user_id, uniqueness: { scope: :item_id }
end
機能
ユーザがあるitemに対して、評価をつける機能
ただし、同じユーザが一つのitemに対して複数評価をつけられないようにしたい
結論
今回はvalidatesはいらない!
DBのユニークインデックスだけで十分ですねってなった
理由
- ユニークバリデーションは内部的に
SELECT
クエリが発行され、DBアクセスが発生する- DB側でも
UNIQUE INDEX
により同じチェックが行われるため 二重チェックになる
- DB側でも
-
validates
は基本的に DBアクセスなしで事前に検証できることに価値があるが、ユニーク性に関しては DBアクセス前提なのでその利点を活かしにくい
つまり、Railsのvalidates機能を使用するメリットがありませんでしたというお話。
ChatGPTにも聞いてみた
Railsのvalidatesって結局いつ使えばいいんだ?
AIに聞いてみたのでまとめておく。
1. ユーザー入力の検証(フォームバリデーション)
- 必須チェック(presence)
- 文字数制限(length)
- 形式制限(format)
- 一致チェック(confirmation)
- 同意確認(acceptance)
2. ビジネスルールの明示と強制
- 数値制限(numericality)
- 値の許容・禁止(inclusion / exclusion)
- 重複チェック(uniqueness ※DB制約と併用)
3. 属性間の依存ロジックの検証
- 日付の前後関係
- 条件付き必須(例: プレミアムユーザーは電話番号必須)
- カスタムバリデーション(
validate :method_name
)
4. UX向上(エラーメッセージ表示)
- フォームにバリデーションメッセージを表示できる
- エラー箇所のフィールドに視覚的にフィードバックできる
5. APIレスポンスに適切なエラーを返す
- 例: 422 Unprocessable Entity + JSONでエラー詳細
6. モデル設計の明確化
- バリデーションがあることで、モデルの使い方がわかりやすくなる
- テストやコードレビューの助けになる
validates
を使うか判断するためのチャート
✅ まとめ
プロダクトの設計思想によってもどうすべきかが変わってくると思うので、今回の結論が他のプロダクトでも当てはまるかはまた別のお話
Discussion