How to Ignore a Folder in Zeitwerk for Rails 6

How to ignore a folder in Zeitwerk for Rails 6?

I ran into this same issue, and it turns out it was complaining about a folder name.

Adding this to application.rb may work for you:

Rails.autoloaders.main.ignore(Rails.root.join('app/junkyard'))

Rails 6 + Zeitwerk, loading files without class

You can tell the main autoloader to ignore them:

# config/initializers/zeitwerk.rb
Rails.autoloaders.main.ignore(
Rails.root.join("app/queries/foo.rb"),
Rails.root.join("app/queries/bar.rb")
)

And then the application is responsible for loading them using require or whatever.

If everything under app/queries should be ignored, you can ignore the directory itself:

# config/initializers/zeitwerk.rb
Rails.autoloaders.main.ignore(Rails.root.join("app/queries"))

Namespacing service objects in Rails 6 with Zeitwerk autoloader

It is not true to say that Zeitwerk eliminates 'the need for namespacing'. Zeitwerk does indeed autoload all the subdirectories of app (except assets, javascripts, and views). Any directories under app are loaded into the 'root' namespace. But, Zeitwerk also 'autovivifies' modules for any directories under those roots. So:

/models/foo.rb => Foo
/services/bar.rb => Bar
/services/registration/add_demo_data.rb => Registration::AddDemoData

If you are already used to loading constants from 'non-standard' directories (by adding to config.autoload_paths), there's usually not much change. There are a couple of cases that do require a bit of tweaking, though. The first is where you are migrating a project that just adds app itself to the autoload path. In classic (pre-Rails 6), this allows you to use app/api/base.rb to contain API::Base, whereas in Zeitwerk it would expect it to contain only Base. That's the case you mention above where the recommendation is to exclude that directory from the autoload path. Another alternative would be to simply add a wrapper directory like app/api/api/base.rb.

The second issue to note is how Zeitwerk infers constants from file names. From the Rails migration guide:

classic mode infers file names from missing constant names
(underscore), whereas zeitwerk mode infers constant names from file
names (camelize). These helpers are not always inverse of each other,
in particular if acronyms are involved. For instance, "FOO".underscore
is "foo", but "foo".camelize is "Foo", not "FOO".

So, /api/api/base.rb actually equates to Api::Base in Zeitwerk, not API::Base.

Zeitwerk includes a rake task to verify autoloading in a project:

% bin/rails zeitwerk:check
Hold on, I am eager loading the application.
expected file app/api/base.rb to define constant Base

Rails custom project structure autoloading configs

You can ignore parts of the project in zeitwerk using Loader#ignore. You can access rails zeitwerk autoloader via Rails.autoloaders.main.

So you should be able to add something like this to your application.rb:

Rails.autoloaders.main.ignore(Rails.root.join('lib/clients/*/config/initializers/*.rb'))

You'll then have to require them manually, maybe in an initializer in the main app directory. You could create a config/initializers/clients.rb with something like:

Dir[Rails.root.join('lib/clients/*/config/initializers/*.rb')].each do |filename|
require filename
end

Zeitwerk doesn't requires lib classes properly in Rails 6.1.6

An autoload path is a root directory, not its contents.

You need to remove the wildcards as documented here.

Best place for Middlewares on Rails 6

Middleware cannot be reloaded because the middleware stack is setup during application boot and never rebuilt.

Because of that, you should tell the main autoloader to ignore the directory:

# config/initializers/zeitwerk.rb
Rails.autoloaders.main.ignore(Rails.root.join("app/middleware"))

and load the file yourself with require or require_relative just like you are doing.

There is some documentation about this use case here.

Autoloading and Zeitwerk Mode in Rails 6

Nothing you have here is deprecated, however one thing worth mentioning is from the documentation:

The array of autoload paths can be extended by mutating config.autoload_paths, in config/application.rb, but nowadays this is discouraged.

Rails 5+ is discouraging the use of manually extending config.autoload_paths because of potential issues it can cause in your production environment. The discussion dates back to 2013 and you can read about it here.

From Rails 5+ all directories under app/ are autoloaded by default. If you'd like to follow the Rails recommendation, you should remove this line

config.autoload_paths += ["#{config.root}/app/queries/"]

and move your queries directory under "#{Rails.root}/app" folder.

Have rails ignore a specific path

All you should need to do is disable Passenger for that directory, and make sure Indexes (directory listings) are allowed. In your Apache <VirtualHost> config block, add:

<Location /shared>
PassengerEnabled off
Options +Indexes
</Location>


Related Topics



Leave a reply



Submit