モデルにバリデーションを追加して入力データを制限しよう
学習の目標
本章では、以下の内容を学習します。
- バリデーションの概念と重要性を理解する
- モデルにバリデーションを追加する方法を習得する
- さまざまな種類のバリデーションとその使い方を学ぶ
- バリデーションに失敗した場合の動作を理解する
- データの整合性を保つための基本的な考え方を身につける
はじめに
これまでに、Railsの基本的なCRUD操作(作成・表示・更新・削除)について学んできました。しかし、ユーザーが入力したデータがそのままデータベースに保存されると、不適切なデータが混入する可能性があります。例えば、タイトルが空のままの投稿や、極端に短い本文などです。
このセクションでは、Ruby on Railsのバリデーション機能を使って入力チェックを行う方法を学びます。バリデーションとは、データの入力チェックを行う機能のことです。バリデーションを適切に設定することで、不正なデータの保存を防ぎ、アプリケーションのデータの整合性を保つことができます。
バリデーションを追加してみる
必須項目の設定(presence)
モデルにバリデーションを追加して入力チェックを行ってみましょう。app/models/post.rb
を開き、以下のように記述します。
class Post < ApplicationRecord
validates :title, presence: true
validates :body, presence: true
end
presence: true
というのは、そのカラム(フィールド)にデータが必ず入るように制約、つまり制限をつけるためのバリデーションです。これによって、タイトルまたは本文が空の場合に保存が失敗するようになります。
このバリデーションを追加した後、以下の操作を試してみましょう。
- 新規投稿ページ (
/posts/new
) にアクセスする - タイトルを空欄にして、「Create Post」ボタンをクリックする
- 画面では何も起きていないように見えるかもしれませんが、一覧ページに戻っても新しいデータが追加されていないことを確認する
同様に、既存の投稿の編集ページを開いて、タイトルを空欄にして更新ボタンを押しても、データは更新されません。
実際には保存や更新に失敗した際、エラーメッセージを表示するようにした方が良いのですが、それは今後の章で学んでいきましょう。
他のバリデーションを試してみる
Railsには presence
以外にも、さまざまなバリデーションが用意されています。ここでは、いくつかの代表的なバリデーションを見ていきましょう。
文字数の制限(length)
タイトルや本文の文字数を制限したい場合は、length
オプションを使用できます。
class Post < ApplicationRecord
validates :title, presence: true, length: { maximum: 50 }
validates :body, presence: true, length: { minimum: 5 }
end
この例では、タイトルは50文字以内、本文は5文字以上でなければなりません。これにより、極端に長すぎるタイトルや短すぎる本文を防ぐことができます。
maximum
と minimum
は同時に設定することもできます。
# 例
validates :title, presence: true, length: { minimum: 10, maximum: 50 }
この場合、タイトルは10文字以上50文字以内という制約が設けられます。
一意性の制約(uniqueness)
タイトルが他の投稿と重複しないようにしたい場合は、uniqueness
オプションを使います。
class Post < ApplicationRecord
validates :title, presence: true, uniqueness: true
end
「ユニーク」とは、他に同じものが存在しないという意味です。このバリデーションによって、同じタイトルの投稿が複数存在しないようになります。
実際のアプリケーションでは、例えばユーザーのメールアドレスやユーザー名など、他のデータと重複しないようにするために使われます。ユーザー登録機能を実装する際には、このバリデーションが非常に重要になります。
その他のバリデーション
Railsには他にも多くのバリデーションがあります。以下に代表的なものをいくつか紹介します。
数値の制限(numericality)
数値のみを許可したり、特定の範囲内の数値のみを許可したりする場合に使用します。
# 例:年齢は数値で、0以上150以下であることを確認
validates :age, numericality: { only_integer: true, greater_than_or_equal_to: 0, less_than_or_equal_to: 150 }
フォーマットの指定(format)
特定のパターンに一致する値のみを許可する場合に使用します。例えば、メールアドレスや電話番号の形式をチェックするなどです。
# 例:メールアドレスの形式をチェック
validates :email, format: { with: /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i }
包含・除外(inclusion, exclusion)
特定の値のみを許可する(または特定の値を禁止する)場合に使用します。
# 例:性別は「男性」「女性」「その他」のいずれかであることを確認
validates :gender, inclusion: { in: ['男性', '女性', 'その他'] }
# 例:予約日は土日でないことを確認
validates :booking_date, exclusion: { in: ->(record) { [record.saturday, record.sunday] } }
バリデーションの動作を理解する
バリデーションは、モデルの save
、create
、update
などのメソッドが呼び出されたときに自動的に実行されます。バリデーションに失敗すると、これらのメソッドは false
を返し、データはデータベースに保存されません。
バリデーションに失敗した場合、モデルの errors
オブジェクトにエラーメッセージが追加されます。このエラーメッセージは、後ほど学ぶフォームのエラー表示などで使用されます。
例えば、コントローラの create
アクションは以下のようになっています。
def create
@post = Post.new(post_params)
if @post.save
redirect_to post_path(@post), notice: "Post was successfully created."
else
render :new
end
end
@post.save
がバリデーションに失敗すると、if
文の条件が false
となり、else
節の render :new
が実行されます。これにより、フォームが再表示され、ユーザーは入力をやり直すことができます。
バリデーションの利点
バリデーションを使用することには、以下のような利点があります。
- データの整合性の確保: 不正なデータがデータベースに入るのを防ぎます。
- ユーザーエクスペリエンスの向上: ユーザーに適切なフィードバックを提供することで、正しいデータを入力するよう促します。
- セキュリティの向上: 悪意ある入力(例:スクリプトインジェクション)からアプリケーションを守ります。
- ビジネスルールの実装: アプリケーションの要件に応じたルールを設定できます。
まとめ
本章では、Railsのバリデーション機能を使って、入力チェックを行う方法を学びました。
presence: true
を使うと、データが必須になるlength
を使うと、文字数の最小・最大を制限できるuniqueness
を使うと、一意性を保証できる- バリデーションに失敗すると、データは保存されず、フォームが再表示される
バリデーションは、アプリケーションのデータの品質と整合性を保つために非常に重要な機能です。適切なバリデーションを設定することで、ユーザーエクスペリエンスの向上やアプリケーションの信頼性の確保につながります。