What if you could change how your program works while it's running, without stopping or rewriting everything?
Why Class_eval and instance_eval in Ruby? - Purpose & Use Cases
Imagine you have a class in Ruby, and you want to add or change methods while your program is running. Doing this by rewriting the whole class or creating many subclasses can be confusing and slow.
Manually changing classes or objects means stopping your program, editing code, and restarting. This is slow and error-prone. You might accidentally break things or create many copies of similar code.
Using class_eval and instance_eval lets you add or change methods directly inside a class or an object while the program runs. This makes your code flexible and powerful without rewriting or restarting.
class Dog def bark puts 'Woof!' end end # To add a new method, you must reopen the class manually
Dog.class_eval do def wag_tail puts 'Wagging tail' end end # Adds method dynamically without reopening class manually
You can change or add behavior to classes and objects on the fly, making your Ruby programs more dynamic and adaptable.
In a web app, you might want to add logging or debugging methods to certain objects only when needed, without changing the original class code or restarting the app.
class_eval changes or adds methods inside a class dynamically.
instance_eval changes or adds methods or variables inside a single object.
Both help make Ruby programs flexible and easier to maintain.
Practice
class_eval and instance_eval in Ruby?Solution
Step 1: Understand
class_evalbehaviorclass_evalopens the class and changes it, so all instances see the change.Step 2: Understand
instance_evalbehaviorinstance_evalruns code in the context of a single object, changing only that object.Final Answer:
class_evalchanges the class and affects all instances;instance_evalchanges only one object. -> Option CQuick Check:
class_eval = class-wide, instance_eval = single object [OK]
- Confusing which method affects the class vs. single object
- Thinking both methods change the whole class
- Assuming instance_eval changes all instances
greet to class Person using class_eval?Solution
Step 1: Recall correct block syntax for class_eval
class_evaltakes a block with method definitions inside curly braces or do-end.Step 2: Check method definition placement
Methodgreetmust be defined inside the block passed toclass_eval.Final Answer:
Person.class_eval { def greet; 'Hi'; end } -> Option AQuick Check:
class_eval uses block with method defs [OK]
- Omitting braces or block for class_eval
- Using instance_eval instead of class_eval for class methods
- Writing method defs outside the block
class Dog
def initialize(name)
@name = name
end
end
fido = Dog.new('Fido')
fido.instance_eval { def speak; "Woof! I'm #{@name}"; end }
puts fido.speak
rex = Dog.new('Rex')
puts rex.respond_to?(:speak)Solution
Step 1: Understand instance_eval adds method to one object
Thespeakmethod is added only tofido, not to other Dog instances.Step 2: Check outputs
fido.speakprints "Woof! I'm Fido".rex.respond_to?(:speak)returns false becauserexhas nospeakmethod.Final Answer:
Woof! I'm Fido false -> Option AQuick Check:
instance_eval adds method to one object only [OK]
- Assuming all instances get the new method
- Expecting true for rex.respond_to?(:speak)
- Confusing instance_eval with class_eval
class Cat
end
kitty = Cat.new
kitty.class_eval { def meow; 'Meow!'; end }
puts kitty.meowSolution
Step 1: Check receiver of class_eval
class_evalis a method of Class, not of instances; calling it on an instance raises NoMethodError.Step 2: Verify execution
Sincekittyis an instance,kitty.class_evalraises NoMethodError; thus,puts kitty.meowis not reached.Final Answer:
NoMethodError because class_eval is called on instance -> Option BQuick Check:
class_eval is a Class method, not instance method [OK]
- Thinking class_eval can be called on instances
- Expecting NoMethodError for instance.class_eval
- Confusing class_eval usage with class-only restriction
class Car
def initialize(model)
@model = model
end
end
car1 = Car.new('Toyota')
car2 = Car.new('Honda')
Car.class_eval do
def info
"Model: #{@model}"
end
end
car1.instance_eval do
def info
"Special Model: #{@model.upcase}"
end
end
puts car1.info
puts car2.infoSolution
Step 1: Understand class_eval adds method to all instances
infomethod added byclass_evalreturns "Model: #{@model}" for all cars.Step 2: Understand instance_eval overrides method for one object
car1.instance_evalredefinesinfoonly forcar1, returning uppercase model with "Special Model:" prefix.Step 3: Check outputs
car1.infoprints "Special Model: TOYOTA";car2.infoprints "Model: Honda".Final Answer:
Special Model: TOYOTA Model: Honda -> Option DQuick Check:
class_eval affects all; instance_eval overrides one [OK]
- Assuming instance_eval changes all instances
- Expecting both outputs to be 'Special Model'
- Confusing which method is called on which object
Ready to prove it?
Pass the test and this pattern moves unknown
