Linus
Linus

Reputation: 4783

Referencing constants from Module

In a tutorial, there are examples querying constants using const_get:

class This
end

p Module.const_get('This').new

and

A_CONSTANT = 42
p Module.const_get('A_CONSTANT')
  1. I can't see any module definition. Why is Module used? Why isn't const_get('This') or self.const_get('This') enough? The class where all this is written in is Object, ancestor of BasicObject.
  2. Does the fact that This is a constant mean that it holds the class definition inside of it? Like as it just could hold the number 42? Or to be clearer, is it the same as:

    This = class
    end
    

    like an unnamed method so I can write p This and get the class definition?

Upvotes: 1

Views: 211

Answers (1)

Boris Stitnicky
Boris Stitnicky

Reputation: 12578

Some nice knowledge you have acquired. But I don't know why are you mentioning metaprogramming in your title, when your question is all about constants. Metaprogramming is something else.

In any case, #const_get is an instance method of Module class, so it won't work at the top level, where the implicit receiver is of Object class. When you write

class Foo; end

Constant Foo gets added to Object:

Object::Foo #=> Foo
Object::Bar #=> error (we didn't define constant Bar)

This constant is available also in other classes, such as

Module::Foo #=> Foo, but with a warning
Array::Foo #=> same Foo with the same warning
Fixnum::Foo #=> ditto

In other words, your Foo defined at toplevel is visible from almost every module. But accessing toplevel constants like this is frowned upon, as this is often not what the programmer intended. You can indeed see that the constant is defined on Object:

Object.constants( false ).include? :Foo #=> true

and not on eg. Module:

Module.constants( false ).include? :Foo #=> false

However, if you use #const_get, the warning message is suppressed and you may come to think that Module::Foo actually exists:

Module.const_get( :Foo ) #=> Foo

It doesn't.

Upvotes: 2

Related Questions