📖 Scenario: Imagine you are working on a Ruby program that manages a simple Car class. You want to dynamically add methods and change behavior at runtime using class_eval and instance_eval.
🎯 Goal: You will create a Car class, then use class_eval to add a method to all cars, and instance_eval to add a method to a single car instance. Finally, you will call these methods to see the results.
📋 What You'll Learn
Create a Car class with an initialize method that sets a @make instance variable
Use class_eval to add a method car_info that returns a string with the car make
Use instance_eval on a car instance to add a method special_feature that returns a custom string
Call and print the results of car_info and special_feature methods
💡 Why This Matters
🌍 Real World
Dynamically changing or adding behavior to classes and objects at runtime is useful in metaprogramming, plugins, or frameworks where flexibility is needed.
💼 Career
Understanding <code>class_eval</code> and <code>instance_eval</code> helps Ruby developers write flexible, dynamic code often required in advanced Ruby applications and libraries.
Progress0 / 4 steps
1
Create the Car class with initialize method
Create a class called Car with an initialize method that takes one parameter make and sets it to an instance variable @make.
Ruby
Hint
Use class Car to start the class. Inside, define def initialize(make) and set @make = make.
2
Add car_info method using class_eval
Use Car.class_eval to add a method called car_info that returns the string "This car is a #{@make}".
Ruby
Hint
Use Car.class_eval do and define def car_info inside the block. Return the string with #{@make}.
3
Add special_feature method to one car instance using instance_eval
Create a new Car instance called my_car with make "Toyota". Then use my_car.instance_eval to add a method called special_feature that returns the string "This car has a sunroof".
Ruby
Hint
Create my_car with Car.new("Toyota"). Then use my_car.instance_eval do to define special_feature method.
4
Call and print car_info and special_feature methods
Print the result of calling car_info on my_car. Then print the result of calling special_feature on my_car.
Ruby
Hint
Use puts my_car.car_info and puts my_car.special_feature to print the messages.
Practice
(1/5)
1. What is the main difference between class_eval and instance_eval in Ruby?
easy
A. class_eval and instance_eval both change the whole class.
B. instance_eval changes the class and affects all instances; class_eval changes only one object.
C. class_eval changes the class and affects all instances; instance_eval changes only one object.
D. class_eval and instance_eval both change only one object.
Solution
Step 1: Understand class_eval behavior
class_eval opens the class and changes it, so all instances see the change.
Step 2: Understand instance_eval behavior
instance_eval runs code in the context of a single object, changing only that object.
Final Answer:
class_eval changes the class and affects all instances; instance_eval changes only one object. -> Option C
Quick Check:
class_eval = class-wide, instance_eval = single object [OK]
Hint: class_eval affects all objects; instance_eval affects one [OK]
Common Mistakes:
Confusing which method affects the class vs. single object
Thinking both methods change the whole class
Assuming instance_eval changes all instances
2. Which of the following is the correct syntax to add a method greet to class Person using class_eval?
easy
A. Person.class_eval { def greet; 'Hi'; end }
B. Person.instance_eval { def greet; 'Hi'; end }
C. Person.class_eval def greet; 'Hi'; end
D. Person.instance_eval def greet; 'Hi'; end
Solution
Step 1: Recall correct block syntax for class_eval
class_eval takes a block with method definitions inside curly braces or do-end.
Step 2: Check method definition placement
Method greet must be defined inside the block passed to class_eval.
Final Answer:
Person.class_eval { def greet; 'Hi'; end } -> Option A
Quick Check:
class_eval uses block with method defs [OK]
Hint: Use curly braces or do-end block with class_eval [OK]
Common Mistakes:
Omitting braces or block for class_eval
Using instance_eval instead of class_eval for class methods
Writing method defs outside the block
3. What will be the output of this Ruby code?
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)
medium
A. Woof! I'm Fido
false
B. Woof! I'm Fido
true
C. NoMethodError for fido.speak
D. Woof! I'm Fido
NoMethodError for rex.speak
Solution
Step 1: Understand instance_eval adds method to one object
The speak method is added only to fido, not to other Dog instances.
Step 2: Check outputs
fido.speak prints "Woof! I'm Fido". rex.respond_to?(:speak) returns false because rex has no speak method.
Final Answer:
Woof! I'm Fido
false -> Option A
Quick Check:
instance_eval adds method to one object only [OK]
Hint: instance_eval adds method to one object only [OK]
Common Mistakes:
Assuming all instances get the new method
Expecting true for rex.respond_to?(:speak)
Confusing instance_eval with class_eval
4. Identify the error in this code snippet:
class Cat
end
kitty = Cat.new
kitty.class_eval { def meow; 'Meow!'; end }
puts kitty.meow
medium
A. No error; outputs 'Meow!'
B. NoMethodError because class_eval is called on instance
C. SyntaxError due to missing block
D. RuntimeError because method already exists
Solution
Step 1: Check receiver of class_eval
class_eval is a method of Class, not of instances; calling it on an instance raises NoMethodError.
Step 2: Verify execution
Since kitty is an instance, kitty.class_eval raises NoMethodError; thus, puts kitty.meow is not reached.
Final Answer:
NoMethodError because class_eval is called on instance -> Option B
Quick Check:
class_eval is a Class method, not instance method [OK]
Hint: class_eval is called on classes, not instances [OK]
Common Mistakes:
Thinking class_eval can be called on instances
Expecting NoMethodError for instance.class_eval
Confusing class_eval usage with class-only restriction
5. Given this code, what will be the output?
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.info
hard
A. Special Model: TOYOTA
Special Model: HONDA
B. Model: Toyota
Model: Honda
C. Model: Toyota
Special Model: HONDA
D. Special Model: TOYOTA
Model: Honda
Solution
Step 1: Understand class_eval adds method to all instances
info method added by class_eval returns "Model: #{@model}" for all cars.
Step 2: Understand instance_eval overrides method for one object
car1.instance_eval redefines info only for car1, returning uppercase model with "Special Model:" prefix.
Step 3: Check outputs
car1.info prints "Special Model: TOYOTA"; car2.info prints "Model: Honda".
Final Answer:
Special Model: TOYOTA
Model: Honda -> Option D
Quick Check:
class_eval affects all; instance_eval overrides one [OK]
Hint: instance_eval overrides method only on one object [OK]
Common Mistakes:
Assuming instance_eval changes all instances
Expecting both outputs to be 'Special Model'
Confusing which method is called on which object
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.