Difference in accessing constant and method defined in eigen class

module M
class Z
class << self
X = “foo”
def bar; 12 ; end
end
end
end

M::Z.bar # => 12
M::Z::X # uninitialized constant M::Z::X (NameError)

When we are able to access the method bar but why not the constant X
?

On Wed, Mar 12, 2014 at 9:40 AM, Arup R. [email protected]
wrote:

module M

When we are able to access the method bar but why not the constant X
?

M::Z evaluates to a class object.

That class object has a singleton method called “bar”, so you can invoke
the method on the class object.

On the other hand that “X” is stored in the set of constants of the
singleton class of M::Z, let’s call it S. M::Z::X looks for “X” in the
constants table of M::Z and its ancestors, since none of them is S, the
lookup fails.

Xavier N. wrote in post #1139583:

On Wed, Mar 12, 2014 at 9:40 AM, Arup R. [email protected]

On the other hand that “X” is stored in the set of constants of the
singleton class of M::Z, let’s call it S. M::Z::X looks for “X” in the
constants table of M::Z and its ancestors, since none of them is S, the
lookup fails.

Okay. Got it.

module M
class Z
Num = 10
class << self
Big = 11
def foo; 12 ; end
end
end
end

M::Z.singleton_class::Big # => 12
M::Z.constants.grep(/Num/) # => [:Num]

Why the below didn’t give me [:Big] ?

M::Z.singleton_class.constants.grep(/Big/) # => [:Bignum]

On Wed, Mar 12, 2014 at 11:03 AM, Arup R. [email protected]
wrote:

Xavier N. wrote in post #1139583:

class Z

Why the below didn’t give me [:Big] ?

M::Z.singleton_class.constants.grep(/Big/) # => [:Bignum]

It does not make sense, I’d bet this is a bug.

Xavier N. wrote in post #1139592:

On Wed, Mar 12, 2014 at 11:03 AM, Arup R. [email protected]
wrote:

Xavier N. wrote in post #1139583:

It does not make sense, I’d bet this is a bug.

I expected, I found another edge case, as you said always. Should I
then go to raise a bug ticket on this ?

Just this unexpected result gave me much pain since morning. I was not
able to figure out, what’s going on there. :frowning:

On Wed, Mar 12, 2014 at 1:20 PM, Arup R. [email protected]
wrote:

Xavier N. wrote in post #1139592:

On Wed, Mar 12, 2014 at 11:03 AM, Arup R. [email protected]
wrote:

Xavier N. wrote in post #1139583:

It does not make sense, I’d bet this is a bug.

I expected, I found another edge case, as you said always. Should I
then go to raise a bug ticket on this ?

I believe so.

It is surprising, because these semantics are generic for classes and
modules. I wonder which code could make #constants behave differently
precisely in a singleton class. I’ll read the implementation later in
case
something rings a bell.

Just this unexpected result gave me much pain since morning. I was not

able to figure out, what’s going on there. :frowning:

Nevertheless, defining constants in singleton classes is really unusual.
Since the constant resolution algorithm checks nesting and the enclosing
class belongs to the nesting, you normally are done associating the
constant to the regular class, and semantically often makes sense
anyway.

Arup R. wrote in post #1139587:

Xavier N. wrote in post #1139583:

On Wed, Mar 12, 2014 at 9:40 AM, Arup R. [email protected]

On the other hand that “X” is stored in the set of constants of the
singleton class of M::Z, let’s call it S. M::Z::X looks for “X” in the
constants table of M::Z and its ancestors, since none of them is S, the
lookup fails.

Okay. Got it.

module M
class Z
Num = 10
class << self
Big = 11
def foo; 12 ; end
end
end
end

M::Z.singleton_class::Big # => 12

Note for future readers - There is a typo in the above line.

M::Z.singleton_class::Big # => 11 (not 12)

M::Z.constants.grep(/Num/) # => [:Num]

Why the below didn’t give me [:Big] ?

M::Z.singleton_class.constants.grep(/Big/) # => [:Bignum]