Rails

【Rails】バリデーションのエラーメッセージを取得・表示・日本語化する方法を完全解説!

Rails

 

今回は、Railsにおけるバリデーションのエラーメッセージを取得・表示・日本語化する方法を解説したいと思います。入力フォームを実装する際、バリデーションに関する知識は必須になるので、ぜひこの機会に復習しておきましょう。

バリデーションとは

まずはじめにバリデーションについておさらいしておきましょう。

フォームなどに入力した値をチェックすることをバリデーションと言います。例えば、ユーザー登録の際にニックネームと生年月日が必須項目だとします。しかし、生年月日を入力せずに次に進んでしまいました。すると、エラーメッセージと共に再度入力ページに戻されると思います。これはバリデーションのチェックに引っかかったためです。

このように、入力フォームを実装する際はバリデーションの知識が必須になってきます。

基本的なバリデーションの記述方法は以下のようになります。モデルに記述するということを覚えておきましょう。

class User < ApplicationRecord
  validates :nickname, presence: true
  validates :birthday, presence: true
end

バリデーションエラーの判別

次にバリデーションに引っかかるかどうか判別するためのコマンドを解説します。エラーメッセージを取得・表示する前に、バリデーションに引っかかるかどうかを確認しなければならないためです。

バリデーションの判別にはvalid?メソッドを使用します。

@user = User.new

@user.valid?
# バリデーションを通過した場合
> true

# バリデーションに引っかかった場合
> false

 

エラーの有無を判別するにはany?メソッドを使用します。

@user = User.new

@user.errors.any?
# エラー有り
> true

# エラー無し
> false

エラーメッセージの取得

では実際にエラーメッセージを取得してみます。

よく使うコマンドとしては以下が挙げられるので覚えておきましょう。エラーメッセージはモデルのerrorsに格納されています。

  • @user.errors
  • @user.errors.full_messages
  • @user.errors.full_messages_for(:symbol)

@user.errors

エラーメッセージをハッシュ形式で取得するコマンドです。「rails c」で以下のように確認することができます。

pry(main)> @user = User.new
pry(main)> @user.save

pry(main)> @user.errors
=>{:email=>["can't be blank"], :password=>["can't be blank"], :nickname=>["can't be blank"]}
「can’t be blank」がエラーメッセージになるね。

@user.errors.full_messages

全てのエラーメッセージを配列で取得するコマンドです。エラーメッセージが複数ある場合はeach文を使ってエラーメッセージを表示させましょう。

pry(main)> @user = User.new
pry(main)> @user.save

pry(main)> @user.errors.full_messages
=>["Email can't be blank", "Password can't be blank", "Nickname can't be blank"]

@user.errors.full_messages_for(:symbol)

対象のシンボルのメッセージを配列で取得するコマンドです。具体的には、:symbolの部分にカラム名が入ります。

pry(main)> @user = User.new
pry(main)> @user.save

pry(main)> @user.errors.full_messages_for(:email)
=>["Email can't be blank"]

エラーメッセージの表示方法

続いて、取得したエラーメッセージを表示する方法を紹介します。

まずは、部分テンプレートでエラーメッセージを作成しましょう。部分テンプレートにする理由は、複数ファイルでエラーメッセージを表示することも考慮するためです。

↓ _error_form.html.erb

<% if user.errors.any? %>
  <div class = "alert">
    <ul>
      <% user.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
    </ul>
  </div>
<% end %>

 

続いてこのエラーメッセージを呼び出したいファイルで設定しましょう。今回はindex.html.erbで呼び出すと仮定します。

↓ index.html.erb

<%= render 'error_form', locals: { user: @user } %>

 

これで、エラーがあった場合はエラーメッセージが表示されると思います。

エラーメッセージの日本語化

先ほどの実装でエラーメッセージを表示させることができました。しかし、このエラーメッセージは英語の表記のままになっています。

そこで最後は、このエラーメッセージを日本語化する設定を行っていきましょう。この設定にはgemである「rails-i18n」を使用します。

まずはGemfileに「rails-i18n」を記載し、bundle installを実行しましょう。

↓ Gemfile

gem 'rails-i18n'

 

↓ ターミナル

$ bundle install

 

 

続いて、デフォルトで日本語のエラーメッセージを使用する設定を行います。

config/application.rbに、以下の一文を追記しましょう。「class ~」の中に記述する点に注意してください。

↓ この記述を追記

config.i18n.default_locale = :ja

 

↓ config/application.rb

require_relative 'boot'

require 'rails/all'

Bundler.require(*Rails.groups)

module アプリケーション名
  class Application < Rails::Application
    config.load_defaults 5.2
    config.i18n.default_locale = :ja
  end
end

 

 

次に、config/locals以下にja.ymlを作成し、日本語表記したい文言を設定します。日本語変換する記述が網羅されたコードがGithub上に載っているので、そこから丸々コピー&ペーストしましょう。

↓ config/locals/ja.yml

ja:
  activerecord:
    errors:
      messages:
        record_invalid: 'バリデーションに失敗しました: %{errors}'
        restrict_dependent_destroy:
          has_one: "%{record}が存在しているので削除できません"
          has_many: "%{record}が存在しているので削除できません"
  date:
    abbr_day_names:
    - 日
    - 月
    - 火
    - 水
    - 木
    - 金
    - 土
    abbr_month_names:
    - 
    - 1月
    - 2月
    - 3月
    - 4月
    - 5月
    - 6月
    - 7月
    - 8月
    - 9月
    - 10月
    - 11月
    - 12月
    day_names:
    - 日曜日
    - 月曜日
    - 火曜日
    - 水曜日
    - 木曜日
    - 金曜日
    - 土曜日
    formats:
      default: "%Y/%m/%d"
      long: "%Y年%m月%d日(%a)"
      short: "%m/%d"
    month_names:
    - 
    - 1月
    - 2月
    - 3月
    - 4月
    - 5月
    - 6月
    - 7月
    - 8月
    - 9月
    - 10月
    - 11月
    - 12月
    order:
    - :year
    - :month
    - :day
  datetime:
    distance_in_words:
      about_x_hours:
        one: 約1時間
        other: 約%{count}時間
      about_x_months:
        one: 約1ヶ月
        other: 約%{count}ヶ月
      about_x_years:
        one: 約1年
        other: 約%{count}年
      almost_x_years:
        one: 1年弱
        other: "%{count}年弱"
      half_a_minute: 30秒前後
      less_than_x_seconds:
        one: 1秒以内
        other: "%{count}秒未満"
      less_than_x_minutes:
        one: 1分以内
        other: "%{count}分未満"
      over_x_years:
        one: 1年以上
        other: "%{count}年以上"
      x_seconds:
        one: 1秒
        other: "%{count}秒"
      x_minutes:
        one: 1分
        other: "%{count}分"
      x_days:
        one: 1日
        other: "%{count}日"
      x_months:
        one: 1ヶ月
        other: "%{count}ヶ月"
      x_years:
        one: 1年
        other: "%{count}年"
    prompts:
      second: 秒
      minute: 分
      hour: 時
      day: 日
      month: 月
      year: 年
  errors:
    format: "%{attribute}%{message}"
    messages:
      accepted: を受諾してください
      blank: を入力してください
      confirmation: と%{attribute}の入力が一致しません
      empty: を入力してください
      equal_to: は%{count}にしてください
      even: は偶数にしてください
      exclusion: は予約されています
      greater_than: は%{count}より大きい値にしてください
      greater_than_or_equal_to: は%{count}以上の値にしてください
      inclusion: は一覧にありません
      invalid: は不正な値です
      less_than: は%{count}より小さい値にしてください
      less_than_or_equal_to: は%{count}以下の値にしてください
      model_invalid: 'バリデーションに失敗しました: %{errors}'
      not_a_number: は数値で入力してください
      not_an_integer: は整数で入力してください
      odd: は奇数にしてください
      other_than: は%{count}以外の値にしてください
      present: は入力しないでください
      required: を入力してください
      taken: はすでに存在します
      too_long: は%{count}文字以内で入力してください
      too_short: は%{count}文字以上で入力してください
      wrong_length: は%{count}文字で入力してください
    template:
      body: 次の項目を確認してください
      header:
        one: "%{model}にエラーが発生しました"
        other: "%{model}に%{count}個のエラーが発生しました"
  helpers:
    select:
      prompt: 選択してください
    submit:
      create: 登録する
      submit: 保存する
      update: 更新する
  number:
    currency:
      format:
        delimiter: ","
        format: "%n%u"
        precision: 0
        separator: "."
        significant: false
        strip_insignificant_zeros: false
        unit: 円
    format:
      delimiter: ","
      precision: 3
      separator: "."
      significant: false
      strip_insignificant_zeros: false
    human:
      decimal_units:
        format: "%n %u"
        units:
          billion: 十億
          million: 百万
          quadrillion: 千兆
          thousand: 千
          trillion: 兆
          unit: ''
      format:
        delimiter: ''
        precision: 3
        significant: true
        strip_insignificant_zeros: true
      storage_units:
        format: "%n%u"
        units:
          byte: バイト
          eb: EB
          gb: GB
          kb: KB
          mb: MB
          pb: PB
          tb: TB
    percentage:
      format:
        delimiter: ''
        format: "%n%"
    precision:
      format:
        delimiter: ''
  support:
    array:
      last_word_connector: "、"
      two_words_connector: "、"
      words_connector: "、"
  time:
    am: 午前
    formats:
      default: "%Y年%m月%d日(%a) %H時%M分%S秒 %z"
      long: "%Y/%m/%d %H:%M"
      short: "%m/%d %H:%M"
    pm: 午後

 

これで全ての設定が完了しました。

まとめ

  • バリデーションとは、フォームなどに入力した値をチェックすることを言う
  • バリデーションの判別にはvalid?メソッドを使用する
  • エラーの有無を判別するにはany?メソッドを使用する
  • エラーメッセージの取得には「@user.errors」、「@user.errors.full_messages」、「@user.errors.full_messages_for(:symbol)」がある
  • エラーメッセージの記述は部分テンプレートで分けたほうが無難
  • エラーメッセージの日本語化には「rails-i18n」を使用する

 

 

今回は、Railsにおけるバリデーションのエラーメッセージを取得・表示・日本語化する方法を解説しました。ややボリュームが多い内容ですが、1つ1つ理解しながら進めていきましょう。