モデルにバリデーションを追加して入力データを制限しよう

学習の目標

本章では、以下の内容を学習します。

  • バリデーションの概念と重要性を理解する
  • モデルにバリデーションを追加する方法を習得する
  • さまざまな種類のバリデーションとその使い方を学ぶ
  • バリデーションに失敗した場合の動作を理解する
  • データの整合性を保つための基本的な考え方を身につける

はじめに

これまでに、Railsの基本的なCRUD操作(作成・表示・更新・削除)について学んできました。しかし、ユーザーが入力したデータがそのままデータベースに保存されると、不適切なデータが混入する可能性があります。例えば、タイトルが空のままの投稿や、極端に短い本文などです。

このセクションでは、Ruby on Railsのバリデーション機能を使って入力チェックを行う方法を学びます。バリデーションとは、データの入力チェックを行う機能のことです。バリデーションを適切に設定することで、不正なデータの保存を防ぎ、アプリケーションのデータの整合性を保つことができます。

バリデーションを追加してみる

必須項目の設定(presence)

モデルにバリデーションを追加して入力チェックを行ってみましょう。app/models/post.rb を開き、以下のように記述します。

class Post < ApplicationRecord
  validates :title, presence: true
  validates :body, presence: true
end

presence: true というのは、そのカラム(フィールド)にデータが必ず入るように制約、つまり制限をつけるためのバリデーションです。これによって、タイトルまたは本文が空の場合に保存が失敗するようになります。

このバリデーションを追加した後、以下の操作を試してみましょう。

  1. 新規投稿ページ (/posts/new) にアクセスする
  2. タイトルを空欄にして、「Create Post」ボタンをクリックする
  3. 画面では何も起きていないように見えるかもしれませんが、一覧ページに戻っても新しいデータが追加されていないことを確認する

同様に、既存の投稿の編集ページを開いて、タイトルを空欄にして更新ボタンを押しても、データは更新されません。

実際には保存や更新に失敗した際、エラーメッセージを表示するようにした方が良いのですが、それは今後の章で学んでいきましょう。

他のバリデーションを試してみる

Railsには presence 以外にも、さまざまなバリデーションが用意されています。ここでは、いくつかの代表的なバリデーションを見ていきましょう。

文字数の制限(length)

タイトルや本文の文字数を制限したい場合は、length オプションを使用できます。

class Post < ApplicationRecord
  validates :title, presence: true, length: { maximum: 50 }
  validates :body, presence: true, length: { minimum: 5 }
end

この例では、タイトルは50文字以内、本文は5文字以上でなければなりません。これにより、極端に長すぎるタイトルや短すぎる本文を防ぐことができます。

maximumminimum は同時に設定することもできます。

# 例
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] } }

バリデーションの動作を理解する

バリデーションは、モデルの savecreateupdate などのメソッドが呼び出されたときに自動的に実行されます。バリデーションに失敗すると、これらのメソッドは 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 が実行されます。これにより、フォームが再表示され、ユーザーは入力をやり直すことができます。

バリデーションの利点

バリデーションを使用することには、以下のような利点があります。

  1. データの整合性の確保: 不正なデータがデータベースに入るのを防ぎます。
  2. ユーザーエクスペリエンスの向上: ユーザーに適切なフィードバックを提供することで、正しいデータを入力するよう促します。
  3. セキュリティの向上: 悪意ある入力(例:スクリプトインジェクション)からアプリケーションを守ります。
  4. ビジネスルールの実装: アプリケーションの要件に応じたルールを設定できます。

まとめ

本章では、Railsのバリデーション機能を使って、入力チェックを行う方法を学びました。

  • presence: true を使うと、データが必須になる
  • length を使うと、文字数の最小・最大を制限できる
  • uniqueness を使うと、一意性を保証できる
  • バリデーションに失敗すると、データは保存されず、フォームが再表示される

バリデーションは、アプリケーションのデータの品質と整合性を保つために非常に重要な機能です。適切なバリデーションを設定することで、ユーザーエクスペリエンスの向上やアプリケーションの信頼性の確保につながります。

Previous
Rails の destroy アクションを理解しよう