I have this code in /lib/my_app/version.rb
module MyApp
VERSION = '3.0.7'
end
When I tried this MyApp::VERSION, I saw this error: uninitialized constant MyApp::VERSION.
Then I tried to add config.eager_load_paths << Rails.root.join("lib")
, and a new error happened: expected file /Users/Documents/big_app/lib/my_app/version.rb to define constant MyApp::Version, but didn't (Zeitwerk::NameError)
The only solution that worked for me was to add require_relative '../lib/my_app/version'
to application.rb config file. But I think it's not the right solution.
Any idea about this issue?
If what you're looking to do is just version your Rails application you can just keep it simple and place the constant in config/application.rb
which is required in the boot process anyways and includes a module encapsulating your application.
# ...
module MyApp
VERSION = '3.0.7'
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 7.0
end
end
The only solution that worked for me was to add require_relative '../lib/my_app/version' to application.rb config file. But I think it's not the right solution.
It's less wrong than your other attempt.
Zeitwerk is really for loading the classes and modules in your application. Constants that are simple scalar values do not need a separate file and autoloaded constants are not available at boot time.
In gems you typically include the version in the lib/my_gem.rb
file which is largely boilerplate anyways. This doesn't make much sense to emulate in a Rails app though.
If you really want a separate file which is done in some gems simply to reduce the amount of churn in the version history of the gemspec file then you just require it manually.
require Rails.root.join('lib/my_app/version')
However again, does this actually make any sense in the context of a Rails app?
lib
in Rails is commonly used for code that doesn't quite fit into /app
and should not be autoloaded. It's the purgatory that code lives in until it's extracted into a separate gem. It's not a very obvious place to place something that's just config.