fxn/zeitwerk

[Question] `Rails.autoloaders.main` is `nil` in initializer (undefined method `push_dir' for nil:NilClass)

adrianthedev opened this issue · 4 comments

This is not an issue with zeitwerk per-se, but this is the best place I came up to ask this question because I know that the people here are knoledgeable about these things.
I apologize if this is innapropiate.

I made and published https://github.com/avo-hq/avo, a Rails engine packaged as a gem.
In my engine.rb file I'm pushing a few directories to the main autoloader using this code:

module Avo
  class Engine < ::Rails::Engine
    isolate_namespace Avo

    initializer "avo.autoload" do |app|
      [
        ["app", "avo", "fields"],
        ["app", "avo", "filters"],
        ["app", "avo", "actions"],
        ["app", "avo", "resources"],
        ["app", "avo", "dashboards"],
        ["app", "avo", "cards"],
        ["app", "avo", "resource_tools"]
      ].each do |path_params|
        path = Rails.root.join(*path_params)

        if File.directory? path.to_s
          Rails.autoloaders.main.push_dir path.to_s
        end
      end
    end
  end
end

It does the job and finds the files it needs to work with.

I have this small percentage of users that run into this issue where the Rails.autoloaders.main object is nil and the app fails to boot up.

My question is, what could cause Rails.autoloaders.main to be nil on initialization? Only two users reported that and I haven't been able to come up with a reason on why it's happening.

Thank you!

fxn commented

I suspect those applications are using the classic autoloader, in which case the Zeitwerk-based autoloaders are not instantiated (this is deliberate).

In your case, the portable solution is to use the Rails API, which works in both autoloading modes:

ActiveSupport::Dependencies.autoload_paths += app_avo_directories

You can delete the if, because Rails does it for you.

Got it! I'm going back to confirm that with the app users.

Thank you for your response!

Closing until I confirm that.

Confirmed that their app was not using zeitwerk. We couldn't find any config.autoloader reference because it was a Rails 5 app.

The fix was adding config.load_defaults 6.1 to config/production.rb.