Reputation: 33084
In a Rails app, I'd like to check if a constant is defined, autoloading it if necessary. The defined?
operator returns false until the autoloading has happened.
defined? Foo # => false :(
Foo # => Foo
defined? Foo # => true
My current workaround is this:
begin
Foo # try to autoload
true
rescue NameError
false
end
Is there a better way to check if a constant is defined, but also autoload it if necessary?
Rationale by request:
The Konacha JS testing framework for Rails should automatically pick up a fixtures Ruby file if it exists. The loading should happen with Rails's auto-loading mechanism, so it benefits from automatic reloading (with config.cache_classes = false
).
Upvotes: 3
Views: 275
Reputation: 138
I had a similar problem, where I was loading inferred constants based on conventions. The problem I had was that any errors in the definition of those classes were being swallowed up.
I came up with this:
def const_presence(const_name)
const_name.constantize
rescue NameError => e
raise e unless e.message =~ /uninitialized constant #{const_name}/
end
This returns nil if the constant is not defined, or the constant if it is, but crucially allows any errors encountered while loading the constant to be raised.
Upvotes: 2
Reputation: 211670
It sounds like you're trying to create a could_be_defined?
method which attempts to auto-load and then returns true
or false
as you've indicated.
There's no way to know for sure if a class exists until you try to use it. This is one of the advantages of a highly dynamic language. The down-side is uncertainty.
Your method of force-loading and testing is the only way to know for sure. Some modules may not be declared via autoload
but in fact generated on the fly as required. Trying to predict what may or may not exist will be unreliable at best.
Upvotes: 3