instance_eval and class_eval | Metaprogramming in ruby -3

Prateek vyas
2 min readFeb 22, 2023

--

change the behaviour of your classes and objects on the fly

Instance_eval

let’s write some basic code for the User class

class User
def initialize(first_name, last_name)
@first_name = first_name
@last_name = last_name
end

def first_name
@first_name
end
end

user = User.new('pratik', 'vyas')
user2 = User.new('milan', 'kumar')

user.instance_eval do
def last_name
@last_name
end
end

user.last_name # => 'vyas'
user2.last_name # => undefined method `last_name' for #<User:0x000055fffe075f68 @first_name="milan", @last_name="kumar">

In the above code we can see that user2.last_name has raised the error. It is because instance_eval evaluates the code in context of instance. which user.

So what will happen if in the place of user.instance_eval if we write User.instance_eval the code will be evaluated in terms of User object itself. Which is a User class itself. Which again means that it will create a class method for ourself.

Let’s try it out.

class User
def initialize(first_name, last_name)
@first_name = first_name
@last_name = last_name
end

def first_name
@first_name
end
end

user = User.new('pratik', 'vyas')
user2 = User.new('milan', 'kumar')

user.instance_eval do
def last_name
@last_name
end
end

User.instance_eval do
def whoami
'You are the class method'
end
end
user.last_name # => 'vyas'
user2.last_name # => undefined method `last_name' for #<User:0x000055fffe075f68 @first_name="milan", @last_name="kumar">
User.whoami # => 'you are the class method'

The above code is executed in context of User instance. That’s the reason we got the class method whoami

Class_eval

class_eval evaluates the code in context of class itself instead of an instance. Let’s see

class User
def initialize(first_name, last_name)
@first_name = first_name
@last_name = last_name
end

def first_name
@first_name
end
end

user = User.new('pratik', 'vyas')
user2 = User.new('milan', 'kumar')

User.class_eval do
def last_name
@last_name
end
end

user.last_name # => 'vyas'
user2.last_name # => 'kumar'

In the above the class_eval evaluated the code in context of User class. So we will have the instance method last_name for all user objects.
class_eval basically reopens the class and add a method inside it just like this

class User
def initialize(first_name, last_name)
@first_name = first_name
@last_name = last_name
end

def first_name
@first_name
end
end

user = User.new('pratik', 'vyas')
user2 = User.new('milan', 'kumar')

# Reopening the User class
class User
def last_name
@last_name
end
end

user.last_name # => 'vyas'
user2.last_name # => 'kumar'

Thanks for giving it a read!

Happy coding :)

--

--

Prateek vyas
Prateek vyas

Written by Prateek vyas

Hello i am prateek vyas working as a ruby developer

No responses yet