LoginSignup
29
30

More than 3 years have passed since last update.

Ruby On Rails のValidation メッセージをカスタマイズする

Posted at

背景

Railsの多言語化にはi18nがよく利用されます。

通常下記のように設定をしますよね

config/locales/*.yml
ja:
  activemodel:
    # モデル名
    models:
      user: "ユーザー"
      attributes:
        # モデル毎の属性名
        user:
          name: "名前"
    # 共通の属性名
    attributes:
      gender: "性別"
  # バリデーションエラー
  errors:
    # テンプレート
    format: "%{attribute}%{message}"
    # エラー毎のメッセージ
    messages:
      blank: "を入力してください"
en:
  # 同じ構造なので略
User.rb
class User < ApplicationRecord
  validates :name, presence: true
end

この時、フォームでnameに空白のままsubmitを実行すると、名前を入力してくださいと表示されます。

ですが、例えばnameが空白の時に名前はフルネームで入力してくださいとか、名前は姓・名で分けてくださいと表示したかった場合どうしますか?

*.ymlmodels.attributes.user.nameerrors.messages.blankを書き換える力技もありますが、これでは保守性0です。

美しくありません。また、

User.rb
class User < ApplicationRecord
  validates :name, presence: { message: '名前はフルネームで入力してください' }
end

上記も悪くないけど、多言語化に対応できていない。

そこで、i18nを用いた、メッセージのカスタマイズ方法を紹介いたします。

解決策

Procを組み合わせます。lambdaでも可能です。

config/locales/*.yml
ja:
  activemodel:
    # 同じ構造なので略
  # バリデーションエラー
  errors:
    messages:
      blank: "を入力してください"
    models:
      user:
        fullname_blank: "名前はフルネームで入力してください"
en:
  # 同じ構造なので略
User.rb
class User < ApplicationRecord
  validates :name, presence: {
    message: -> (rec, data) {
      I18n.t('activemodel.errors.models.user.fullname_blank')
    }
  }
end

これを実行すると、うまく多言語化されると思います。

ちなみに、Procを使わないとうまく多言語化されないので気をつけてください。下記が悪い例です。

User.rb
class User < ApplicationRecord
  validates :name, presence: {
    message: I18n.t('activemodel.errors.models.user.fullname_blank')
  }
end

参考

29
30
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
30