Skip to content

Rails 6.0 x zeitwerk の環境において units_directory_path が固定されてしまう場合がある #71

@aqla114

Description

@aqla114

背景

cookpad_all では Rails 6.0 で zeitwerk を使っている状況で Chanko を使っています。
また Chanko::Config の設定については config/initializers 以下に Chanko 用のファイルを用意してそこで各種値を設定しており、そこで unit を置くディレクトリを Chanko::Config.units_directory_path = "app/extensions" で変更しています。

問題

上で設定した units_directory_path が反映されず、デフォルトである app/units で固定されてしまいます。

原因

Chanko::Config は一度 units_directory_path を読み出そうとしたタイミングで現在の @units_directory_path の値をキャッシュしています。

def units_directory_path
@resolved_units_directory_path ||= Rails.root.join(@units_directory_path).to_s
end

また、zeitwerk 環境下では以下のコードにより before: :set_autoload_paths のタイミングで Chanko::Loader.prepare_eager_load が呼び出されます。これは initializers 以下のコードが実行されるよりも前のタイミングです。

initializer("chanko.zeitwerk.prepare_eager_load", before: :set_autoload_paths) do |app|
# zeitwerk freezes autoload_paths after :set_autoload_paths.
# So we need to prepare before set_autoload_paths
Chanko::Loader.prepare_eager_load(mode: :zeitwerk)
end

この prepare_eager_load の中で Chanko::Config::units_directory_path が読み出されているんですが、その時点ではまだ units_directory_path がデフォルト値なのでそちらの値でパスが固定されます。

Rails.autoloaders.main.collapse(Chanko::Config.units_directory_path + '/*')

確認したいこと

  • この仕様は意図したしようでしょうか。
  • もし意図した挙動であれば少しハマりやすいポイントなので、以下のような対応をしたいです。
    • ドキュメントにパスの設定は initializers ではなく application.rb や environment などに書くことを記述する。
    • @resolved_units_directory_path に一度値が入ってしまった場合、 @units_directory_path にいくら値を入れても Chanko で利用するパスは変更できないので、units_directory_path=(path)@resolved_units_directory_path が nil でないときに例外を吐くなどをしたい。
  • もし意図していない挙動であればちょっと修正方針を考えたいです。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions