Ruby gives you the ability to modify a class or an object on-the-fly. You may have seen examples of code written like the examples below.
Example 1: instance_eval
person.instance_eval do
def name
@name.capitalize
end
end
Example 2: class_eval
Person.class_eval do
def name
@name.capitalize
end
end
At first glance, the two blocks of code look very similar. But if you look closely, you’ll see that the first example is calling instance_eval
on person
, an instance of the class Person
. The second example is calling class_eval
on the actual Person
class.
So what is the difference, you might ask?
Let me illustrate.
Suppose we have the Person
class defined and have created two instances of Person
: person1
and person2
.
class Person
def initialize(name)
@name = name
end
end
person1 = Person.new("bob")
person2 = Person.new("jane")
Now let’s apply this code:
person1.instance_eval do
def name
@name.capitalize
end
end
What happens when we call person1.name
? How about person2.name
?
If you guessed person1.name
returns “Bob”, then you are correct. But does person2.name
return “Jane”?
Let’s see:
irb(main):014:0> person1.name
=> "Bob"
irb(main):015:0> person2.name
=> NoMethodError (undefined method `name' for #<Person:0x00007f9beb9539c0 @name="jane">)
That’s right – instance_eval
only evaluates in the context of one object. Only the particular instance that instance_eval
is called on is injected with the name method. In this case, person1
has access to the name
method, but not person2
.
Now you might be tempted to call instance_eval
on person2
, which will make the name
method accessible to person2
. But what happens if you have person3
and person4
? It doesn’t make sense to duplicate code. We want to make sure that the method is shared by all objects of the Person
class.
If you guessed to use class_eval
, you’re right. class_eval
defines an instance method for the class, so that all instances of that class have access to the method. Let’s see:
Person.class_eval do
def name
@name.capitalize
end
end
irb(main):042:0> person1.name
=> "Bob"
irb(main):043:0> person2.name
=> "Jane"
irb(main):044:0> person3 = Person.new("Susan")
=> #<Person:0x00007f9bef866ef0 @name="Susan">
irb(main):045:0> person3.name
=> "Susan"
irb(main):046:0> person4 = Person.new("Mike")
=> #<Person:0x00007f9beb9009a0 @name="Mike">
irb(main):047:0> person4.name
=> "Mike"
All instances of the Person
class, new and old, can now call name
. Defining a method with class_eval
is syntactically the same as defining it in the actual class.
Person.class_eval do
def name
@name.capitalize
end
end
is exactly equivalent to:
class Person
def name
@name.capitalize
end
end
I hope this has helped your understanding of Ruby’s instance_eval
and class_eval
methods. Just remember that you can only call instance_eval
on an object of a class and class_eval
on a class. The instance_eval method defines a method for one object only, whereas the class_eval method defines it for ALL objects or instances of a class.
See our latest technology team opportunities
If you see a position that suits, why not apply today?
We create this content for general information purposes and it should not be taken as advice. Always take professional advice. Read our full disclaimer
This block is configured using JavaScript. A preview is not available in the editor.