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
Get Chromes Console Log via Ruby Webdriver
Problem Using Openstruct with Erb
Remove Subdomain from String in Ruby
Missing File in Gem After Build
How to Access the Current Node from a Library in a Chef Cookbook
How to More Elegantly Remove Duplicate Items Across All Elements of a Ruby Array
Ruby - Calling Setters from Within an Object
Ruby on Rails: Confirmation Page for Activerecord Object Creation
How to Find Gems That Depend on a Given Gem
If 'Main' Is an Instance of 'Object', Why Can't I Call It
How to Print Stdout Immediately
How to Get Long Filename from Argv
Symbol#To_Proc with Custom Methods