Bird
Raised Fist0
Rubyprogramming~3 mins

Why Class_eval and instance_eval in Ruby? - Purpose & Use Cases

Choose your learning style10 modes available
The Big Idea

What if you could change how your program works while it's running, without stopping or rewriting everything?

The Scenario

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.

The Problem

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.

The Solution

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.

Before vs After
✗ Before
class Dog
  def bark
    puts 'Woof!'
  end
end

# To add a new method, you must reopen the class manually
✓ After
Dog.class_eval do
  def wag_tail
    puts 'Wagging tail'
  end
end

# Adds method dynamically without reopening class manually
What It Enables

You can change or add behavior to classes and objects on the fly, making your Ruby programs more dynamic and adaptable.

Real Life Example

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.

Key Takeaways

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

(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

  1. Step 1: Understand class_eval behavior

    class_eval opens the class and changes it, so all instances see the change.
  2. Step 2: Understand instance_eval behavior

    instance_eval runs code in the context of a single object, changing only that object.
  3. Final Answer:

    class_eval changes the class and affects all instances; instance_eval changes only one object. -> Option C
  4. 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

  1. Step 1: Recall correct block syntax for class_eval

    class_eval takes a block with method definitions inside curly braces or do-end.
  2. Step 2: Check method definition placement

    Method greet must be defined inside the block passed to class_eval.
  3. Final Answer:

    Person.class_eval { def greet; 'Hi'; end } -> Option A
  4. 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

  1. Step 1: Understand instance_eval adds method to one object

    The speak method is added only to fido, not to other Dog instances.
  2. Step 2: Check outputs

    fido.speak prints "Woof! I'm Fido". rex.respond_to?(:speak) returns false because rex has no speak method.
  3. Final Answer:

    Woof! I'm Fido false -> Option A
  4. 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

  1. Step 1: Check receiver of class_eval

    class_eval is a method of Class, not of instances; calling it on an instance raises NoMethodError.
  2. Step 2: Verify execution

    Since kitty is an instance, kitty.class_eval raises NoMethodError; thus, puts kitty.meow is not reached.
  3. Final Answer:

    NoMethodError because class_eval is called on instance -> Option B
  4. 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

  1. Step 1: Understand class_eval adds method to all instances

    info method added by class_eval returns "Model: #{@model}" for all cars.
  2. 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.
  3. Step 3: Check outputs

    car1.info prints "Special Model: TOYOTA"; car2.info prints "Model: Honda".
  4. Final Answer:

    Special Model: TOYOTA Model: Honda -> Option D
  5. 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 unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard