2

Given that I have a constant name of Foo::Bar::Baz, how can I drill down through each of these levels and determine if the constant exists?

Kyle Decot
  • 19,418
  • 35
  • 132
  • 245
  • 1
    Is your question whether `Foo::Bar` and `Foo` exist? AFAIK, Ruby won't create `Foo::Bar::Baz` unless `Foo::Bar` already exists. – Neil Slater May 24 '13 at 20:45

4 Answers4

3
defined?(Foo) # => nil

module Foo; end
defined?(Foo) # => "constant"
defined?(Foo::Bar) # => nil

module Foo::Bar; end
defined?(Foo::Bar) # => "constant"
defined?(Foo::Bar::Baz) # => nil

module Foo::Bar; Baz = :baz end
defined?(Foo::Bar::Baz) # => "constant"
sawa
  • 156,411
  • 36
  • 254
  • 350
1

Here's what I ended up doing in case anyone else runs into this:

unless Object.const_defined? const_name
  const_name.split('::').inject(Object) do |obj, const|
    unless obj.const_defined? const
      # create the missing object here...
    end
    obj.const_get(const)
  end
end
Kyle Decot
  • 19,418
  • 35
  • 132
  • 245
1

It sounds like you want to use the defined? operator. Check if a constant is already defined has more on this.

Community
  • 1
  • 1
Puhlze
  • 2,554
  • 16
  • 15
1

Other people talk about the defined? operator (yes, it's a built-in unary operator, not a method!!!), but there are other ways. I personally favor this one:

constants #=> a big array of constant names
constants.include? :Foo #=> false
module Foo; end
constants.include? :Foo #=> true
Foo.constants.include? :Bar #=> false
module Foo
  module Bar; end
end
Foo.constants.include? :Bar #=> true
# etc.

One thing I have to admit about defined? operator is its reliability. It is not a metho and thus can never be redefined, and thus always does what you expect of it. On the other hand, it is possible to use more roundabout (and less reliable) ways, such as:

begin
  Foo::Bar::Baz
  puts "Foo::Bar::Baz exists!"
rescue NameError
  puts "Foo::Bar::Baz does not exist!"
end
Boris Stitnicky
  • 11,743
  • 4
  • 50
  • 69