Rails

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

Rails

 

今回は、Railsにおけるバリデーションのエラーメッセージを取得・表示・日本語化する方法について紹介したいと思います。Railsにおいてバリデーションに関する知識は必須ですが、忘れがちな部分でもあるので自身の備忘録としてもまとめています。

バリデーションとは

バリデーションとは、データベースに保存する前に保存内容を検証する機能です。

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

バリデーションとは

 

このように、何かしらの値をデータベースに保存する機能を実装する際はバリデーションの知識が必須になってきます。

バリデーションの基本形

基本的なバリデーションの記述方法は以下のようになります。

ここではユーザーのニックネーム(nickname)と誕生日(birthday)の存在チェックを行っています。nicknamebirthdayが空であれば保存は行われません。

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

以下のようにワンライナーで記述することも可能です。

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

バリデーションの判別

RailsはActiveRecordオブジェクトを保存する直前にバリデーションを実行し、バリデーションで何らかのエラーが発生するとオブジェクトを保存しません。

その一方でバリデーションを手動で実行することも可能です。

その際に使用するメソッドがvalid?(invalid?)メソッドです。

valid?メソッドはバリデーションを実行しエラーがない場合はtrueを、エラーがある場合にはfalseを返します。(invalidメソッドはその反対です。)

class User < ApplicationRecord
  validates :nickname, presence: true
end
@user = User.new(nickname: 'タロウ')
@user.valid?
> true
@user = User.new(nickname: nil)
@user.valid?
> false

エラーメッセージの取得

バリデーションが行われた後でerrorsメソッドを使うことで、発生したエラーメッセージを取得することができます。

errors

errorsメソッドはエラーメッセージをハッシュ形式で取得するコマンドです。

class User < ApplicationRecord
  validates :nickname, presence: true
  validates :birthday, presence: true
end
@user = User.new(nickname: nil, birthday: nil)
@user.valid?
@user.errors
=>{:nickname=>["can't be blank"], :birthday=>["can't be blank"]}

errors.full_messages

errors.full_messagesメソッドは全てのエラーメッセージを配列で取得するコマンドです。エラーメッセージが複数ある場合で1つずつ表示したい場合は、eachmapといった繰り返し処理を使ってエラーメッセージを表示させることになります。

class User < ApplicationRecord
  validates :nickname, presence: true
  validates :birthday, presence: true
end
@user = User.new(nickname: nil, birthday: nil)
@user.valid?
@user.errors.full_messages
=> ["Nickname can't be blank", "Birthday can't be blank"]

errors.full_messages_for(:symbol)

errors.full_messages_for(:symbol)メソッドは指定した属性のエラーメッセージを配列で取得するコマンドです。

class User < ApplicationRecord
  validates :nickname, presence: true
  validates :birthday, presence: true
end
@user = User.new(nickname: nil, birthday: nil)
@user.valid?
@user.errors.full_messages_for(:email)
=> ["Nickname can't be blank", "Birthday can't be blank"]

エラーメッセージの表示

エラーメッセージを表示するにはエラーの有無を検知し、errorsに格納されているエラーメッセージを取得・表示する必要があります。

例えば、以下のようなコードをビューファイルに記述することで表示が可能になります。

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

user.errors.any?でUserモデルに対するエラーの有無を検知します。その後エラーがあればuser.errors.full_messages.eachが実行され、繰り返し処理によって存在するエラーが全て表示されるようになります。

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

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

ここではエラーメッセージを日本語化する設定を行っていきます。

この設定にはgemである「rails-i18n」を使用します。

gem 'rails-i18n'
% bundle install

 

デフォルトではロケールが英語(:en)になっているため、デフォルトの設定を日本語(:ja)に変更します。ロケールはapplication.rbで設定することができます。

module HomecareRails
  class Application < Rails::Application
    # 以下の1行を追加
    config.i18n.default_locale = :ja
  end
end

 

続いてconfig/locales配下にja.ymlを作成し、日本語変換したい文言を設定します。

% touch config/locales/ja.yml
ja:
  activerecord:
    attributes:
      user:
        nickname: ニックネーム
        birthday: 誕生日

 

ここまでの設定でエラーメッセージが日本語されているはずです。

class User < ApplicationRecord
  validates :nickname, presence: true
  validates :birthday, presence: true
end
@user = User.new(nickname: nil, birthday: nil)
@user.valid?
@user.errors.full_messages
=> ["ニックネームを入力してください", "誕生日を入力してください"]

エラーメッセージを1つ1つ個別設定すると面倒なので、ja.ymlテンプレートの使用がおすすめです。使いたいエラーメッセージがテンプレートにない場合は自身で追記していく形になります。

 

エラーメッセージのカスタマイズ

前項ではエラーメッセージを日本語化しましたが「〜を入力してください」のように、「を入力してください」でエラーメッセージが固定されていました。

ここでは、エラーメッセージをカスタマイズする方法について紹介します。

翻訳ファイルであるja.ymlを以下のように編集します。

ja:
  activerecord:
    attributes:
      user:
        nickname: ニックネーム
        birthday: 誕生日
    errors:
      models:
        user:
          blank: が未入力です

 

これにより「〜を入力してください」の部分が「〜が未入力です」に変換されます。

class User < ApplicationRecord
  validates :nickname, presence: true
  validates :birthday, presence: true
end
@user = User.new(nickname: nil, birthday: nil)
@user.valid?
@user.errors.full_messages
=> ["ニックネームが未入力です", "誕生日が未入力です"]

バリデーションとメッセージの関係は以下のようになっています。

バリデーション利用可能なオプションメッセージ式展開
confirmation:confirmationattribute
acceptance:accepted
presence:blank
absence:present
length:within, :in:too_shortcount
length:within, :in:too_longcount
length:is:wrong_lengthcount
length:minimum:too_shortcount
length:maximum:too_longcount
uniqueness:taken
format:invalid
inclusion:inclusion
exclusion:exclusion
associated:invalid
non-optional association:required
numericality:not_a_number
numericality:greater_than:greater_thancount
numericality:greater_than_or_equal_to:greater_than_or_equal_tocount
numericality:equal_to:equal_tocount
numericality:less_than:less_thancount
numericality:less_than_or_equal_to:less_than_or_equal_tocount
numericality:other_than:other_thancount
numericality:only_integer:not_an_integer
numericality:in:incount
numericality:odd:odd
numericality:even:even

参考: エラーメッセージ内での式展開

 

しかしこのままの記述だと、blankのエラーメッセージが全て「〜が未入力です」に変換されてしまいます。特定の属性毎に、例えばUserモデルのnicknameカラムに対してのみエラーメッセージを指定したい場合は以下のようにja.ymlを記載します。

ja:
  activerecord:
    attributes:
      user:
        nickname: ニックネーム
        birthday: 誕生日
    errors:
      models:
        user:
          attributes:
            nickname:
              blank: は必須入力です

 

これにより、属性毎にエラーメッセージをカスタマイズすることができます。

class User < ApplicationRecord
  validates :nickname, presence: true
  validates :birthday, presence: true
end
@user = User.new(nickname: nil, birthday: nil)
@user.valid?
@user.errors.full_messages
=> ["ニックネームは必須入力です", "誕生日を入力してください"]

フォーマットのカスタマイズ

これまでのエラーメッセージでは「ニックネームを入力してください」や「誕生日を入力してください」のように「属性名(attribute) + エラーメッセージ(message)」で固定されていました。

ここではフォーマットをカスタマイズする方法について紹介します。

まずはapplication.rbに以下の1行を追加します。

module HomecareRails
  class Application < Rails::Application
    config.i18n.default_locale = :ja

    # 以下の1行を追加
    config.active_model.i18n_customize_full_message = true
  end
end

 

続いてja.ymlを以下のように編集します。

ja:
  activerecord:
    attributes:
      user:
        nickname: ニックネーム
        birthday: 誕生日
    errors:
      models:
        user:
          attributes:
            nickname:
              format: "%{attribute}: %{message}"
              blank: 未入力

 

これにより、属性毎にフォーマットをカスタマイズすることができます。

class User < ApplicationRecord
  validates :nickname, presence: true
  validates :birthday, presence: true
end
@user = User.new(nickname: nil, birthday: nil)
@user.valid?
@user.errors.full_messages
=> ["ニックネーム: 未入力", "誕生日を入力してください"]

まとめ

  • バリデーションとは、データベースに保存する前に保存内容を検証する機能のこと
  • バリデーションを手動で実行するにはvalid?(invalid?)メソッドが使用できる
  • エラーの有無を判別するにはany?メソッドが使用できる
  • エラーメッセージの日本語化には「rails-i18n」を使用する
  • エラーメッセージのカスタマイズはja.ymlで行うことができる

参考

Active Record バリデーション

 

今回はRailsにおけるバリデーションのエラーメッセージを取得・表示・日本語化する方法について紹介しました。バリデーションを使いこなせることはRailsエンジニアの基本の1つなので参考になれば幸いです。