I am upgrading a Rails 5.2.2 to Rails 6.0.0 that now has Zeitwerk.
Previously I had been extended core ruby classes like Date, Time, String, Float etc as described in this question. Using an initializers file to load all files from the lib/core_ext/*
folder. When starting a rails server
it now errors an the last line of the stacktrace reads:
/home/username/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/zeitwerk-2.1.10/lib/zeitwerk/loader.rb:351:in `const_get': uninitialized constant CoreExt::Date (NameError)
Unfortunately, Zeitwerk is causing an error where lib/core_ext/date.rb
etc is throwing an error that it has already been defined (when using Rails.autoloaders.log!
in application.rb
. CoreExt::Date
I have since moved the files directly to initializers
(previously I just had the initializers directory with a file that loaded each file from the 'lib/core_ext/*
folder). This has fixed the issue for now but I'd like to keep core_ext
folder and files where they were.
What have I missed here?
lib/core_ext/date.rb
class Date
def to_sap
strftime('%d.%m.%Y')
end
end
I have tried wrapping explicitly in CoreExt
but that did not help.
module CoreExt
class Date
def to_sap
strftime('%d.%m.%Y')
end
end
end
As is saying on https://github.com/fxn/zeitwerk#file-structure
loader.push_dir(Rails.root.join("app/models"))
loader.push_dir(Rails.root.join("app/controllers"))
And by Zeitwerk author: https://github.com/rails/rails/issues/37835#issuecomment-560563560
The lib folder does not belong to the autoload paths since Rails 3. @pixeltrix's is the recommended modern idiom if you want to autoload. Otherwise, lib belongs to $LOAD_PATH and you can require files in that directory.
We can call push_dir to load the lib subdirectories. My solution:
# config/initializers/zeitwerk.rb
Rails.autoloaders.main.push_dir(Rails.root.join('lib'))
or
# config/application.rb
...
config.autoload_paths += [
Rails.root.join('lib')
]
Then CoreExt::Date
can be auto loaded.
I have the same structure by extending core functionality and adding files in lib/extensions
I solved this by adding
# config/application.rb
#
class Application < Rails::Application
...
Rails.autoloaders.main.ignore(Rails.root.join('lib/extensions'))
end
And I keep initializing extensions as previously:
Dir[Rails.root.join('lib', 'extensions', '**', '*.rb')].each { |f| require f }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With