I'm using a Ruby on Rails 5.2.8 and Ruby 2.7.8 version and I have found a bug in code. The code should check at runtime if a model is defined. At first I tried to use the defined?
method, but because the development environment lazy loads the modules I have encountered unexpected (for me) behaviour:
defined?(ModelToCheck) #=> nil
ModelToCheck
defined?(ModelToCheck) #=> true
so only after using the model it appears to be defined. What is the best way to check if it is defined?
P.S.
the option which configures the lazy loading is:
# config/environments/development.rb
ExampleApp::Application.configure do
config.eager_load = false
# rest of the config
# ...
end
For now I tried to use also Object.const_defined?
method, but the same story again.
I have two ideas:
begin
rescue
blocks to handle NameError
when it is not defined, however it is ugly and I wouldn't like to use it if I couldSince the author of the questions did not want to use #defined?
or Object.const_defined?
due to autoloading issues, I came up with another solution.
Yet the best solution would be to fix the autoloading issue, but it's hard to judge that without knowing the internals of the project.
A way to achieve this is is using #missing_name
or #missing_name?
and rescuing the thrown NameError
:
begin
HelloWorld
rescue NameError => e
e.missing_name
end
# => "HelloWorld"
See the docs for more details.
Since you find that ugly you can also wrap this into a method something like this:
def check_defined(constant)
!!Oject.const_get(constant)
rescue NameError => e
!e.missing_name?(constant)
end