Railsのindex_errorsでi18nを適用する際にハマったのと、それを調べる過程について
要約
- index_errorsでi18nを使うときは config.active_model.i18n_customize_full_message = true を指定すること
- 一次情報が大事。Qiita等を見るのはそのあと。
- 困ったときはとりあえずprintデバッグから始めてみる。順を追って行けばそれなりに読める。
本文
Railsで1対多の関係(has_many)において、どの子要素でエラーが出たのかを載せるindex_errorsという機能がある。
index_errorsについては下記参照。
github.com
しかし、この機能困ったことにエラーのキーに上記を見ると分かるが、エラーのキーにindexが入ってくるため、i18nでエラーメッセージを変換するのがなかなか難しいのが個人的に難点だった。
だが、Rails6.0ではこれに対し、indexを除いた値をi18nで参照するような修正がなされているということで、おお素晴らしいとアップデートの日を心待ちにしていた。
github.com
しかし、アップデートしたもののどうだろうか、エラー表示は変わらなかった。
しかも、特に調べてみてもその辺りに関する言及は出てこなかった。
(accepts_nested_attributes_forが市民権を得てないからかな?笑)
どうやらデフォルトでONになるわけではないようである。
仕方ないので、binding.pryしながらコードを読み進めていくと、下記のコードでindexを削るか否かの判定をしていることが分かった。
if self.class.i18n_customize_full_message && @base.class.respond_to?(:i18n_scope)
@base.class.respond_to?はtrueだったが、self.class.i18n_customize_full_messageはfalseだったので、処理が走らないという状況だった。
(ちなみに、self.classはActiveModel::Errors、@base.classはフォームで操作しているオブジェクト)
では、このi18n_customize_full_messageをどこで操作しているのか。
まずActiveModel::Errors内でi18n_customize_full_messageを見ると、デフォルトでfalseがセットされているっぽいことが分かった。
class << self attr_accessor :i18n_customize_full_message # :nodoc: end self.i18n_customize_full_message = false
そこで次はrailsリポジトリ内でi18n_customize_full_messageを検索してみる。 そうすると、testファイルを除いてrailtie.rbとconfigure.mdがヒットした。
railtie.rbを見ると、どうやらconfigで何か指定しなくてはならないことが読み解ける。
initializer "active_model.i18n_customize_full_message" do ActiveModel::Error.i18n_customize_full_message = config.active_model.delete(:i18n_customize_full_message) || false end
そして、configure.mdを見るとバッチリ書いてあった。
config.active_model.i18n_customize_full_message is a boolean value which controls whether the full_message error format can be overridden at the attribute or model level in the locale files. This is false by default.
というわけで、config/application.rbに下記の内容を追加する。
module Aftshop class Application < Rails::Application # other config.. config.active_model.i18n_customize_full_message = true end end
すると、indexを除いたi18n_keyの内容を無事、参照してくれるようになった。
教訓
一次情報をよく見るべし、とつよつよエンジニアの方々はよく言うが、今回は身を以て経験した感じ。
そして、改めて大事だなと思ったのは2つ。
1. 公式リポジトリを見る習慣
2. rails等のフレームワークのコードも、順に追っていけば案外読める
Railsのコードも、一つの巨大な塊と考えてしまうと、どこからアプローチしていけばいいのか分かりにくい。
でも、binding.pry等を駆使して、順に処理を追って行けば、意外と読めるなという感覚。
どんなに優れたコードとて、所詮は同じ人間が書いたもの。
そんな感じで気楽に構えたらいいのかなーと思った。