I understand the basic difference between instance_eval
and class_eval
. What I've discovered though when playing around is something strange involving attr_accessor
. Here's an example:
A = Class.new
A.class_eval{ attr_accessor :x }
a = A.new
a.x = "x"
a.x
=> "x" # ... expected
A.instance_eval{ attr_accessor :y }
A.y = "y"
=> NoMethodError: undefined method `y=' for A:Class
a.y = "y"
=> "y" # WHATTT?
How is it that:
- the instance_eval didn't at the accessor onto our A class (object)
- it then in fact added it onto instances of A?
At first, your understanding (or intuition) is correct, methods defined inside
#instance_eval
and#class_eval
are not the samea side note: while
self
is the same in bothinstance_eval
andclass_eval
, the default definee is different, see http://yugui.jp/articles/846What really does the trick is
Module#attr_accessor
itself, look at its definition: http://rxr.whitequark.org/mri/source/vm_method.c#620it does not use
def
, it does not read context,self
or a default definee. It just "manually" inserts methods into a module. That's why the result is counterintuitive.