はじめに
Railsのバリデーションには元から多くの種類が用意されておりエンジニアはそれらを活用して効率的に開発を進めることができますが、種類が多く頭の中で整理しきれていないと感じています。
今回はバリデーションについて基礎からまとめていき、自分の整理用としてまとめていきたいと思います🧑💻
バリデーションとは
データベースに保存する前に、データが正しいかどうかをチェックする仕組みです!
例えば、ユーザー登録の際にメールアドレスが正しい形式であるか、パスワードが一定の長さを満たしているかなどを確認します。
バリデーションを行う理由
有効なデータのみをデータベースへ保存し、無効なデータが保存されるのを防ぐためです。
バリデーションによって、データの整合性と品質を保つための「門番」の役割を果たします!
少し強引ですが人間に例えると、「食べ物に毒が入っていないか?」「そもそも食べられるものなのか?」確認作業を行うイメージ🔍
モデルレベル以外でのバリデーション
Railsで開発する際には、モデルレベルでバリデーションを行うことがベストプラクティスとされていますが、他にも以下のようなレベルでバリデーションを行うことも方法としてあります。
下記のようなメリットデメリットがありますが、デメリットの部分が大きいため、基本的にはモデルレベルでのバリデーションが推奨⚠️
| レベル | メリット・利用場面 | デメリット |
|---|---|---|
| データベース | ・Rails以外からもDBを参照する場合 ・モデルレベルのバリデーションの補完 |
・テストや保守の難易度が高い |
| クライアントサイド | ・ユーザー体験の向上(即時フィードバック) | ・セキュリティリスク(容易に回避可能) |
| コントローラーレベル | (基本的には推奨されない) | ・コードの重複や複雑化 ・テストと保守の難易度が高い |
バリデーションが実行されるタイミング
バリデーションは、「オブジェクトの状態をデータベースに保存(永続化)しようとした直前」に実行されます!
具体的には、SQL(INSERTやUPDATE)が実行される直前にバリデーションが行われ、もしバリデーションに失敗するとSQLは発行されず、保存処理がロールバックされます。
バリデーションが実行されるメソッド
| メソッド名 | 説明 | 失敗時の挙動 |
|---|---|---|
save |
オブジェクトを保存 | 保存されずfalseを返す |
save! |
同上 | ActiveRecord::RecordInvalid 例外が発生し、処理が止まる |
create |
オブジェクトの作成と保存(save)を一度に行う | そのオブジェクトを返すだけ |
create! |
同上 | ActiveRecord::RecordInvalid 例外が発生し、処理が止まる |
update |
既存のオブジェクトを更新 | 保存されずfalseを返す |
update! |
同上 | ActiveRecord::RecordInvalid 例外が発生し、処理が止まる |
また、SQL(INSERTやUPDATE)の実行は必要ないが、バリデーションだけを実行したい場合には、以下のメソッドを使用できます。
| メソッド名 | 説明 | 返り値 |
|---|---|---|
valid? |
オブジェクトが有効かどうかをチェック | 有効のときはtrue、無効のときはfalse
|
invalid? |
オブジェクトが無効かどうかをチェック | 無効のときはtrue、有効のときはfalse
|
バリデーションがスキップされるメソッド
先ほど、「オブジェクトの状態をデータベースに保存(永続化)しようとした直前」にバリデーションが実行されると説明しましたが以下のメソッドでは、バリデーションがスキップされるため使用する際には注意が必要です😮
| メソッド名 | 説明 |
|---|---|
insert |
単一レコードを直接挿入 |
insert! |
単一レコードを直接挿入(失敗時に例外) |
insert_all |
複数レコードを一括挿入 |
insert_all! |
複数レコードを一括挿入(失敗時に例外) |
toggle! |
真偽値属性を反転させて即座に保存 |
touch |
updated_at/updated_onを現在時刻に更新 |
touch_all |
複数レコードのupdated_atを一括更新 |
update_all |
複数レコードを条件指定で一括更新 |
upsert |
レコードが存在すれば更新、なければ挿入 |
upsert_all |
複数レコードをupsert処理 |
save(validate: false) |
バリデーションを明示的にスキップして保存 |
他にもスキップするメソッドがありますので、詳細はRailsガイドをご参照ください。
バリデーションでエラーが発生したとき
バリデーションでエラーが発生したとき、そのエラー内容はerrorsオブジェクトに格納されます。
このerrorsオブジェクトを利用することで、どの属性でどのようなエラーが発生したのかを確認することができます。
# Userモデル
class User < ApplicationRecord
validates :name, presence: true
end
# Railsコンソール
user = User.new(name: "")
user.valid? # => false
user.errors[:name]
# => ["を入力してください"]
errorsオブジェクトが持つ便利なメソッドがいくつかあるのですが、長くなりそうなので、また別の記事でまとめたいと思います💪
errorsオブジェクトとは?
-
ActiveModel::Errorsクラスのインスタンスで、モデルオブジェクトに関連するバリデーションエラー情報を格納・管理するためのオブジェクト - ActiveRecordインスタンスの
errorsメソッドを通じてアクセス可能 -
Enumerableモジュールをインクルードしているため、反復処理が可能
Part2へ続く
参考記事

