I was trying to get Matz and Flanagan’s “Ruby Programming Language” metaprogramming chapter into my head, However I couldn’t understand the output from the following code snippet that I dreamed up:
p Module.constants.length # => 88
$snapshot1 = Module.constants
class A
NAME=:abc
$snapshot2 = Module.constants
p $snapshot2.length # => 90
p $snapshot2 - $snapshot1 # => ["A", "NAME"]
end
p Module.constants.length # => 89
p Module.constants - $snapshot1 # => ["A"]
p A.constants # => ["NAME"]
The book states that the class method constants returns the list of constants for the class (as you can see in the output for A.constants).
I was trying to get the list of constants defined for the Module class when I came across the above strange behavior.
A‘s constants show up in Module.constants. How do I get the list of constants defined by the Module class?
The docs state
Module.constantsreturns all constants defined in the system. including names of all classes and methods
Since A inherits its implementation from Module.constants, how does it behave differently in the base and derived types?
p A.class # => Class
p A.class.ancestors # => [Class, Module, Object, Kernel]
Note: If you’re using Ruby 1.9, constants would return an array of symbols instead of strings.
Good question!
Your confusion is due to the fact that the class method
Module.constantshides the instance methodModule#constantsforModule.In Ruby 1.9, this has been addressed by adding an optional parameter:
In your example above,
A.constantscallsModule#constants(the instance method), whileModule.constantscalls, well,Module.constants.In Ruby 1.9, you thus want to call
Module.constants(true).In Ruby 1.8, it is possible to call the instance method
#constantsonModule. You need to get the instance method and bind it as a class method (using a different name):I wish I was able to backport the 1.9 functionality completely to 1.8 for my
backportsgem, but I can’t think of a way to get only the constants of a Module, excluding the inherited ones, in Ruby 1.8.Edit: Just changed the official documentation to correctly reflect this…