J
jdance
David Black wrote in Ruby For Rails (page 341):
The subject of singleton methods and constants has recently gotten me
into trouble. Here is a simplified example:
module ExtendMeFirst
BAR = 3
end
module ExtendMeSecond
def print_bar
puts BAR
end
end
class A
extend ExtendMeFirst
extend ExtendMeSecond
end
A.print_bar #=> NameError: uninitialized constant ExtendMeSecond::BAR
Now, I somewhat understand why this doesn't work - the constants are in
different scopes. The challenge is to get around this problem and use
the constant BAR from ExtendMeFirst in module ExtendMeSecond. We
discovered that what we needed to was access the singleton class's
constants, but there is basically no easy way to do this, since there
is no "singleton_class" method in Object/Kernel (which has been
discussed a long time ago on this list). We eventually added one:
class Object
def singleton_class
class << self; self; end
end
end
And then doing this allowed us to get to the constant:
module ExtendMeSecond
def print_bar
puts singleton_class::BAR
end
end
Is there a better way to do this? What is the "arcane point" about
singleton methods and constants?
(There's also a subtle difference between these two approaches to
defining a singleton method, involving the scope of constants, but that's an
arcane point. For the most part, you can treat them as equivalent.)
The subject of singleton methods and constants has recently gotten me
into trouble. Here is a simplified example:
module ExtendMeFirst
BAR = 3
end
module ExtendMeSecond
def print_bar
puts BAR
end
end
class A
extend ExtendMeFirst
extend ExtendMeSecond
end
A.print_bar #=> NameError: uninitialized constant ExtendMeSecond::BAR
Now, I somewhat understand why this doesn't work - the constants are in
different scopes. The challenge is to get around this problem and use
the constant BAR from ExtendMeFirst in module ExtendMeSecond. We
discovered that what we needed to was access the singleton class's
constants, but there is basically no easy way to do this, since there
is no "singleton_class" method in Object/Kernel (which has been
discussed a long time ago on this list). We eventually added one:
class Object
def singleton_class
class << self; self; end
end
end
And then doing this allowed us to get to the constant:
module ExtendMeSecond
def print_bar
puts singleton_class::BAR
end
end
Is there a better way to do this? What is the "arcane point" about
singleton methods and constants?