Where are Singleton Constant Ruby constants stored?

Suppose we have this Ruby class:

class MyClass class << self MC_CONST = 30 end end 

Then create an instance of MyClass and add another constant to the metaclass of the object:

 m = MyClass.new class << m OBJ_MC_CONST = 50 end 

No problem with the singleton constant of an object:

 m.singleton_class::OBJ_MC_CONST # => 50 <-- [OK] m.singleton_class.constants.include? :OBJ_MC_CONST # => true <- [OK] 

But not quite what I would expect with a singleton class constant:

 MyClass.singleton_class::MC_CONST # => 30 <-- [OK] MyClass.singleton_class.const_get :MC_CONST # => 30 <-- [OK] MyClass.singleton_class.constants.include? :MC_CONST # => false <-- [Why???] 

Why doesn't the array returned by the .constants method in the metaclass of the MyClass class contain: MC_CONST? What am I missing here?

Thanks.


EDIT 1: This seems to be a bug in MRI 2.x. I registered a new problem with the main Ruby team: https://bugs.ruby-lang.org/issues/9413 to solve this problem.

EDIT 2: This error seems to be fixed at https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/44628/diff/

+7
ruby singleton constants
source share
1 answer

I studied this question a bit, and I think it is caused by an MRI error / inconsistency / idiosyncrasy.

In MRI 2.1.0 this code is:

 class MyClass class << self MC_CONST = 30 end end p MyClass.singleton_class.const_defined? :ABBA_CONST, false p MyClass.singleton_class.const_defined? :MC_CONST, false p MyClass.singleton_class.constants(false) 

gives

 false true [] 

Thus, the MC_CONST constant MC_CONST defined, but it is not available as a local class constant (I pass false values ​​to various methods to disable constant resolution and just keep it local for this class), which should be true. If we check the documentation of the constants of module #, then it says:

Returns an array of constant names available in the module. This includes the names of the constants in any included modules (an example at the beginning of the section) if all is not set to false.

Also see module :: const_defined? .

So what do we need to check const_defined? to better understand the behavior of constants , but these two methods give different results!


In addition, in another Ruby implementation, this code works as expected.

In JRuby 1.7.9 it gives:

 false true [:MC_CONST] 

In Rubinius 2.2.1, it gives:

 false true [:MC_CONST] 

What is the expected behavior :)

+5
source share

All Articles