14 February 2017
A Gotcha in Ruby Constant Lookup
Given a namespace Foo
(it can be a class or a module),
module Foo
MEOW = "meow"
end
…there are two ways to open a class within that namespace.
class Foo::Bar
# ...
end
# --- or ---
module Foo
class Bar
# ...
end
end
However, the first version does not have access to constants attached to the outer namespace,
module Foo
MEOW = "meow"
end
class Foo::Bar
def get_meow
MEOW
end
end
Foo::Bar.new.get_meow
#=> NameError: uninitialized constant Foo::Bar::MEOW
…whereas the second version does.
module Foo
MEOW = "meow"
end
module Foo
class Bar
def get_meow
MEOW
end
end
end
Foo::Bar.new.get_meow
#=> "meow"
Explanation
Module.nesting
allows you to inspect the list of namespaces that will
be searched through during constant lookup. Using it, we can see that the
first version does not add Foo
to the lookup list,
class Foo::Bar
Module.nesting
end
#=> [Foo::Bar]
…whereas the second version does.
class Foo
class Bar
Module.nesting
end
end
#=> [Foo::Bar, Foo]