This post explains the difference between class_eval
and instance_eval
methods in Ruby. If you keep getting confused between them when reading or writing Ruby code, it should clarify things a little.
Consider the Greeting
class, which forms the basis of other examples.
class_eval
class_eval
evaluates the string or block in the context of the class, allowing you to reopen the class and define additional behavior on it.
Creating a method inside the block defines an instance method on the class. All Greeting
instances can call greet
.
This is the same as explicitly defining the greet
method in the Greeting
class. The above code is equivalent to:
Benefits
- The first benefit of
class_eval
is that you can call it on a variable pointing to a class, allowing you to add behavior to a class dynamically. - When using
class_eval
, the code will fail immediately, if the class doesn’t exist (or if you misspelled the class name). So you can’t accidentally add code to a class that doesn’t exist.
The class_eval
method is only available on classes (modules, to be precise). You can’t call it on instances, i.e. instance_name.class_eval
doesn’t exist. Ruby throws the error undefined_method class_eval
.
instance_eval
instance_eval
evaluates the code in the context of the receiving object. When you call it on a class, e.g. ClassName.instance_eval
, the receiving object is the class, which is an instance of Class
. For example, Greeting
is an instance of Class
.
irb(main):043:0> Greeting.class
=> Class
If you create a method inside the block, it defines a class method. It’s associated with the class object but not visible to instances of that class.
When the code is executing, the variable self
is set to the receiving object to set the context, giving the code access to the object’s instance variables and private methods.
Similarly, calling instance_eval
on an instance, e.g. instance_name.instance_eval
defines a method on that specific instance. No other instances of the class can access that method.
Summary
class_eval
evaluates the string or block in the context of the class, allowing you to reopen the class and define additional behavior on it.instance_eval
evaluates the string or block in the context of the receiver object, allowing you to run code as if we were inside a method of this object, giving access to its private methods.