class Foo
@@x = 10
end
Foo.class_eval(’@@x’) # => 10 # Part-I
Foo.class_eval{ @@x } # => # Part - II
~> -:5:in `block in ': uninitialized class variable @@x in
Object (NameError)
~> from -:5:in `class_eval’
~> from -:5:in `’
Why does Part-I and Part-II behave differently ?
Here’s a snippet I wrote while playing around:
class Foo; class_eval{ @@x }; end
=> 10
This leads me to believe it might be a scoping or lookup issue? There
seems
to be a rule at play here that I can’t put my finger on. I’m a bit
confused
only because the following works:
class Foo; @x = 42; end
=> 42
Foo.class_eval{ @x }
=> 42
Hi Arup R.,
The Ruby documentation gives a clue …
class_eval(string [, filename [, lineno]]) → obj
Evaluates the string or block in the context of mod, except that when
a block is given, constant/class variable lookup is not affected.
Source:
http://www.ruby-doc.org/core-2.1.0/Module.html#method-i-class_eval
So, when you do
Foo.class_eval { @@x }
… with a block given, the scope of @@x doen’t change and @@x is
“scoped” on Object.
I try to think this as simply as an iterator having access to the
surrounding local vars.
collection = [ “bananas”, “oranges”, “apples”]
local_var = "I like "
collection.each { |fruit| puts local_var + fruit }
So, class_eval just “try” to get the “@@x” from the outermost context
(not inside the Foo class).
class Foo
@@x = 10
end
The context where this @@x bellow is it is Object
Foo.class_eval { @@x }
=> NameError: uninitialized class variable @@x in Object
class Bar
Foo.class_eval { @@x }
end
=> NameError: uninitialized class variable @@x in Bar
Inside the “class Bar” definition, @@x is scoped on Bar, not Object.
More…
At Dave T. book we can read…
“Class variables belong to the innermost enclosing class or module.
Class variables used at the top level are defined in Object, and
behave like global variables. Class variables defined within singleton
methods belong to the receiver if the receiver is a class or a module;
otherwise, they belong to the class of the receiver.”
Source:
http://www.ruby-doc.org/docs/ruby-doc-bundle/ProgrammingRuby/book/language.html
In a newer version it says “Class variables defined within singleton
methods belong to the top level (although this usage is deprecated and
generates a warning).”
Try this also:
class Foo
@@x
end
I think this is like class_eval with a String
Foo.class_eval("@@x")
class << Foo # The eingenclass of the Foo class
@@x
end
(ruby 1.8.7) warning: class variable access from toplevel singleton
method
(ruby 2.1.0) warning: class variable access from toplevel
NameError: uninitialized class variable @@x in Object
I think this is like class_eval with a block
Foo.class_eval { @@x }
More important than the above is to remember that we should favor
class instance variables rather than class variables when possible.
http://jvans1.github.io/blog/2013/01/06/class-variables-vs-class-instance-variables/
It’s just less complicated! 
Abinoam Jr.