I have an old Rails 3.x application that I now migrate to 7.x (It is/was already running under 5.0, so it is not so hard). However, I planed to do this step by step, but it is more or less impossible to install older versions 2023.
The application runs nice and (almost) without any require
s with 3.x. Therefore I assume, that I kept the naming conventions.
Edit from: But zeitwerk ignores all my constants, to: But zeitwerk ignores all my Classes and Modules,
not complicated things I read in other Q&A, that are tricky. No just easy things.
I bring two examples, that I think zeitwerk should find, but doesn't
I have a config\initializers\site_init.rb
that I use to configure some of my modules.
Site.setup do |config|
config.default_do_say=false
config.default_show_all_exceptions=false
end
Site::Cache.setup do |config|
…
end
So I would expect zeitwerk to find it in lib/site/cache.rb
where it is defined like that:
module Site
class Cache
include Singleton
extend Configurable
configurable_local_name 'config', 'setup'
configurable_all_to_module
configurable_global cache_path: "./tmp/cache"
configurable_global auto_file_size: 1000
configurable_global auto_persist: 100
...
The second is also easy (config/initializers/bot_check.rb
):
BotCheck.setup do |config|
config.etw_divider=20
config.etw_min_level=0
end
Located in controllers
directly
module BotCheck
extend Configurable
configurable_local_name 'config', 'setup'
configurable_all_to_module
# configurable_global start_time: Time.now
configurable_global etw_divider: 5
configurable_global etw_min_level: 0
def self.check_level
count=BotResult.where("created_at > ?", Time.now()-1.hour).count()
Rails.logger.warn "bot check level: #{count}, #{config.etw_min_level}".white.on_red
[count/config.etw_divider, config.etw_min_level].max
end
end
rails zeitwerk:check
tells me:
/config/environment.rb:5:in -> NameError: uninitialized constant BotCheck
You see, I struggle early. That's why I am sure, that I have overseen or not understood something very basic of zeitwerk.
The relevant part of application.rb
looks like
if Rails.version < "7"
config.autoload_paths += %W(#{config.root}/app/helpers)
config.autoload_paths += %W(#{config.root}/app/helpers/fields)
config.autoload_paths += %W(#{config.root}/app/helpers/tags)
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += %W(#{config.root}/lib/geo_lib)
config.autoload_paths += %W(#{config.root}/lib/tech_draw)
config.autoload_paths += %W(#{config.root}/lib/site)
config.autoload_paths += %W(#{config.root}/lib/inplace_trans)
config.autoload_paths += %W(#{config.root}/lib/flat_form)
config.autoload_paths += %W(#{config.root}/lib/site_tag_helper)
else
config.load_defaults 7.0
config.add_autoload_paths_to_load_path=false
puts "---------------- 7777777 -----------------"
config.eager_load = false
config.autoload_paths << "#{config.root}/lib"
config.autoload_paths << "#{config.root}/lib/site"
puts config.eager_load_namespaces
end
#check for typos
config.autoload_paths.each { |p| puts "autoload_paths: #{p}"; puts "#{p} not found or no directory".yellow if !File.directory?(p) }
config.eager_load_paths.each { |p| puts "eager_load_paths: #{p}"; puts "#{p} not found or no directory".yellow if !File.directory?(p) }
Wow, that is a big jump!
The ability to autoload reloadable constants while the application boots was deprecated in Rails 6, and removed in Rais 7.
This was a technical change, unrelated to Zeitwerk. Basically, autoloading reloadable code during initialization is a bad idea because initializers do not run on reload, so whatever edits you do to that code won't be reflected.
The guide Autoloading and Reloading Constants has a section about referring to reloadable constants in the initializers that could help.
It would also be a good idea to read Classic to Zeitwerk HOWTO.
One last remark, the application should have zero require
calls for autoloadable application files, I recommend that you delete them all, they could be hiding something that is not right, and could in some edge cases make things go wrong.
The point of autoloading is to not use require
at all. This advice is also unrelated to Zeitwerk, and was present in the guide for the classic
autoloader too. Of course, you still use require
for 3rd party code in gems as usual, this remark only applies to your own autoloadable code.
After deleting them, please run bin/rails zeitwerk:check
, if there's any mismatch between file names and expected constants that will show it.