Zeitwerk で特別なパターンのモジュール/クラス名をオートロードする
Rails 6.0 から Zeitwerk がオートローダーとして導入されました。 Zeitwerk の README に書かれている通り、ファイルパスからモジュールやクラスを読み込みます。
モジュール/クラス名がファイルパスになっていれば良いのですが、特別なパターンだと名前を解決できない場合があります。
クラス名に頭字語を使っている場合
例えば、クラス名に頭字語を使っている場合です。
以下のログがその例で、lib/ridgepole/dsl_parser.rb
というファイルパスを Zeitwerk は Ridgepole::DslParser
と想定しています。
しかし、実際のクラス名は Ridgepole::DSLParser
なので名前の解決に失敗しています。(bin/rails zeitwerk:check
は Zeitwerk が使用できるかチェックするタスク)
% bin/rails zeitwerk:check
Hold on, I am eager loading the application.
expected file lib/ridgepole/dsl_parser.rb to define constant Ridgepole::DslParser,
対応方法
どうすればいいかというと、Rails ガイドのオートロードについて書かれているページには、config/initializers/inflections.rb
をカスタマイズしましょうとあります。
If you need to customize any of these inflections, for example to add an acronym, please have a look at config/initializers/inflections.rb.
ActiveSupport::Inflector
モジュールには活用形をカスタマイズする機構があるので、Zeitwerk もそれを参照する形になっているようです。
以下は Zeitwerk が ActiveSupport::Inflector
の設定をテストしている箇所です。
今回の場合は、dsl
を DSL
と解決したいので、config/initializers/inflections.rb
を以下のように定義します。
ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.acronym "DSL"
end
再度 bin/rails zeitwerk:check
を実行してみると、無事に解決できました。
% bin/rails zeitwerk:check
Hold on, I am eager loading the application.
All is good!
今回は Rails アプリ側で対応しましたが、理想を言うなら、ライブラリ側の名前を変更するほうが使う側にとって良いのでは、と思ったりもします。