Reputation: 7719
Looking for an explanation why in the following example in Module.class_eval
block, class variables lookup does not work:
class MyClass
@@myvar = 123
def self.myvar_getter
@@myvar
end
end
class MyClass
p "#{self}, #{self.object_id}, #{singleton_class.object_id}"
# output: "MyClass, 21055520, 21055500"
p myvar_getter # class method lookup working
# output: 123
p @@myvar # class variable lookup working
# output: 123
end
MyClass.class_eval do
p "#{self}, #{self.object_id}, #{singleton_class.object_id}"
# output: "MyClass, 21055520, 21055500"
p myvar_getter # class method lookup working as expected
# output: 123
p @@myvar # class variable lookup NOT working (why ?)
# output: -- following exception --
# a.rb:47: warning: class variable access from toplevel
# a.rb:47:in `block in <main>': uninitialized class variable
# @@myvar in Object (NameError)
end
As you may see the scope seems to be identical, self
is the same, class method :myvar_getter
is found in both cases, but class variable @@myvar
is unexpectedly looked up in Object
class within class_eval
block.
Can anybody explain this behavior other than because ?
Upvotes: 0
Views: 624
Reputation: 7719
I've had to experience some weak moment, as the answer is quite clear & obvious.
From the Module.class_eval
documentation:
Evaluates the string or block in the context of mod, except that when a block is given, constant/class variable lookup is not affected. This can be used to add methods to a class. module_eval returns the result of evaluating its argument.
So if I would need directly access class variables from eval block (ie. without use of class variable getter/setter methods), I'd just pass the code as a string:
MyClass.class_eval <<-EOS
p @@myvar # class variable lookup is working from a string
# output: 123 voila!
EOS
Upvotes: 1