Jo Liss
Jo Liss

Reputation: 33084

defined? for autoloadable classes

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

Answers (2)

i2w
i2w

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

tadman
tadman

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

Related Questions