instance_eval
and class_eval
allow you to execute a chunk of code. So what you might say? The old-fashioned eval
can do this. But instance_eval
and class_eval
accept a block argument for the chunk of code. So the chunk of code does not need to be a string. Also instance_eval
and class_eval
allow a receiver (unlike the old eval
). Consequently, you can invoke these two modern methods on a class object or even on an instance object.
class A
end
A.instance_eval do
# self refers to the A class object
self
end
a = A.new
a.instance_eval do
# self refers to the a instance object
self
end
Also remember in ruby if we call a method without a receiver, then the method would be invoked on self
, which in the instance_eval
block is the object we invoked instance_eval
on. instance variables are private in ruby. You cannot access them outside the class they are defined in. But since instance variables are stored in self
, we can access them in instance_eval
(the same applies for private methods which cannot be invoked with a receiver):
class A
def initialize
@a = “a”
end
private
def private_a
return “private a”
end
end
a = A.new
puts a.instance_eval { @a }
# => “a”
puts a.instance_eval { private_a }
# => “private a”
We can also add methods to the receiver in instance_eval
and class_eval
. Here we add it to instance_eval
:
class A
end
A.instance_eval do
def a_method
puts “a method”
end
end
A.a_method
# => a method
Now think what we just did for a moment. We used instance_eval
, defined a method in its block
, and then invoked the method on the class object itself. Isn’t that a class method? Think of it as a “class” method if you want. But all we did was define a method on the receiver in the instance_eval
block, and the receiver happened to be A
. We can easily do the same on a instance object:
a.instance_eval do
def a_method
puts "a method"
end
end
a.a_method
# => a method
And it works just the same. Don’t think of class methods as class methods in other languages. They are just methods defined on self
, when self
happens to be a class object (extending from Class.new
as in class A end
).
But I want to take this answer a little bit more deeper than the accepted answer. Where does instance_eval
actually stick the methods you place into them? They go into the singleton
class of the receiver! As soon as you invoke instance_eval
on the receiver, the ruby interpreter opens the singleton_class
and places the methods defined in the block inside this singleton_class
. It is just like using extend
in a class (because extend opens up the singleton class and places the methods in the module passed to extend into the singleton class)! It opens up the singleton_class
, which is part of the inheritance hierarchy (right before the parent class): A -> singleton_class -> Parent
Now what makes class_eval
different? class_eval
can only be called on classes and modules. self
still refers to the receiver:
class A
end
A.class_eval do
# self is A
self
end
But unlike instance_eval
, when you define methods in the class_eval
block, they will be available on instances of the class not the class object itself. With class_eval
, the methods are not added to the singleton class in the inheritance hierarchy. Instead the methods are added to the current class
of the receiver! So when you define a method in class_eval
, that method goes directly into the current class
and, thus, it becomes an instance method. So you cannot call it on the class object; you can only call it on instances of the class object.