食べチョク開発者ブログ

食べチョクエンジニアによるプロダクト開発ブログ

Railsバリデーションメッセージのリソース名を特定するパッチの話

こんにちは。食べチョクの開発をお手伝いしているフリーランスエンジニアのもぎゃ です。
ぼくも記事書いていいそうなので、最近食べチョクの開発をやっている時に発見したRailsテクニックの話を書きます。

バリデーションメッセージのつらみ

Railsでバリデーションをつかって入力をチェックしている場合、@model.errors.full_message をエラーメッセージとして出すことができます。

Active Record バリデーション - Railsガイド

ただ、ぼくらが作ったモデルの日本語名までRailsが知っていてくれるわけではないので、"User Messageを入力してください"みたいな分かりづらい文字列になってしまうことがあって、この場合i18nのリソースを適切に書いてあげることでエラーメッセージを改善することが出来ます。

Rails 国際化 (i18n) API - Railsガイド

ということで、エラーメッセージのカスタマイズについては公式ドキュメントに書いていただいているのですが、現場のRailsのモデルは"User"みたいにシンプルなものではなくて、"Users/address"みたいにnamespaceがついていたり、modelではなくformオブジェクトのバリデーションだったり、accepts_nested_attributes_forを使っていたりすると、「え、これどこに名前を書けばいいの?」となることもしばしば。

この場合、エラーメッセージは「リソースが適切な位置にあれば使われる」というヒントしかないので、うまく行かない場合、「これか?」「ここなのか?」「これもちがうの?」という"当て物ゲーム"を繰り返すしかないのが辛いところです。
「もう良いからif文書いて自前のエラーメッセージにしようぜ」みたいなごまかした実装をするたびに、ControllerがFat化していく...

そもそも、「リソースが適切な位置にあれば使われる」というルールである以上、i18nのライブラリは"正解"のリソースを読みに行っているはずです。そのリソース名を教えてくれたら一発じゃない!?

リソース名を教えてくれるモンキーパッチ

細かい実装はさておき、最終的にはi18n.tを呼び出しているはずです。i18n.tのエイリアス元であるtranslateメソッドの実装はこちら。

  def translate(key = nil, *, throw: false, raise: false, locale: nil, **options) 

i18n/i18n.rb at master · ruby-i18n/i18n · GitHub

この最初のkeyが目的のリソース名です。じゃあ最初からこれを教えてよ。ということでパッチを書きました。

ファイル名は何でも良いので、config/initializerの下におきます。

  module I18nMonkeyPatch
    def translate(key = nil, *, throw: false, raise: false, locale: nil, **options)
      Rails.logger.warn "***************************************************"
      Rails.logger.warn "i18nMonkeyPatch key: #{key}"
      Rails.logger.warn "***************************************************"
      super
    end
  end

  I18n.singleton_class.prepend(I18nMonkeyPatch)

そうすると、i18nの変換が行われるたびにログにリソース名が出力されるので、該当箇所を実行してみればこんな感じでリソース名が分かるようになります

 ***************************************************
 i18nMonkeyPatch key: activerecord.attributes.order_inquiry_thread/lines.message
 ***************************************************

ということで、こういうリソースファイルを作ればよいようです

  ja:
    activerecord:
      attributes:
        'order_inquiry_thread/lines':
          message: "メッセージ"

答えを知ってしまえば、"i18n モデル スラッシュ"とかでググってそれらしい記述を見つけ出せるのですが、そもそもなぜ駄目なのかがわからないと検索キーワードすらわからないので、一発で答えを得られるパッチはそれなりに使い所があるのではないかなと思います。

最後に

食べチョクでは、開発者の方を募集しております。
ぼくみたいにフリーランスの立場から開発に参加してissueをガシガシ消化していけるエンジニアも必要だし、急成長する会社の屋台骨として開発を推進できる社員さんはもっともっと必要そうです。

この記事を見て、「おおそんなやり方が」と思った方、ぜひ一緒にやりましょう!
「その程度かよ」と思った人、野菜の新しい流通経路を作るためにぜひその腕前を貸してください!

www.wantedly.com
www.wantedly.com