skip to content

In Ruby, calling Report.instance_eval versus Report.class_eval on a class, what is self in each block, and where does a def inside it land?

level: seniorimportance: must knowfreq 55%

answer

  1. same self, different definee
  2. instance_eval: singleton class
  3. class_eval: the class itself
  4. method calls still follow self
  5. _exec variants take arguments

basics

~10 s

Both set self to Report. They differ in the default definee: a def inside Report.instance_eval becomes a singleton method, Report.x, while a def inside Report.class_eval becomes an instance method, Report.new.x.

solid answer

~40 s

Each eval context sets `self` and a **default definee**, the module where a bare `def` puts its method. `obj.instance_eval` sets `self` to `obj` and the definee to `obj`'s singleton class, so on a class it creates class methods. `mod.class_eval` (alias `module_eval`) sets `self` to `mod` and the definee to `mod`, so it creates instance methods, as reopening the class would. `instance_exec` and `class_exec` do the same but pass their arguments to the block. The trap: only `def` uses the definee. `define_method` and `attr_accessor` are method calls on `self`, so `Report.instance_eval { attr_accessor :title }` still creates instance-level accessors. `class_eval` exists only on `Module`; `instance_eval` works on any object.

code

ruby · 18 lines
ruby
class Report; end

Report.instance_eval do
  def generate = "class-level"            # def: goes to Report's singleton class
  define_method(:footer) { "instance" }   # call on self (Report): instance method
  attr_accessor :title                    # call on self: instance accessors
end

Report.class_eval do
  def generate = "instance-level"         # def: goes to Report itself
end

Report.generate                 # => "class-level"
Report.new.generate             # => "instance-level"
Report.new.footer               # => "instance"
Report.respond_to?(:title)      # => false
Report.instance_eval { self }   # => Report
Report.class_eval { self }      # => Report

go deeper

for a junior

Recall that class_eval adds instance methods like reopening the class, while instance_eval on a class adds class methods.

for a middle

Explain self versus the default definee, and show that the _exec variants differ only in passing arguments to the block.

for a senior

Show the trap that def follows the definee while define_method and attr_accessor follow self, and choose class_exec for stored procs that need caller values.

for a principal

Argue for generated methods living in class_eval blocks with plain def or define_method, so readers see class-body rules rather than definee tricks.

## Two things an eval context sets When Ruby runs code, it tracks more than `self`. It also tracks the **default definee**: the module that receives a method when the code executes a bare `def name`. In ordinary code the two travel together in an obvious way: inside `class Report ... end`, `self` is `Report` and a `def` defines an instance method of `Report`. The eval family is where they come apart, and interviewers test exactly that. ## The four methods | Method | Defined on | `self` in the block | A bare `def` goes to | Block arguments | |---|---|---|---|---| | `instance_eval` | `BasicObject` | the receiver | the receiver's singleton class | the receiver | | `instance_exec` | `BasicObject` | the receiver | the receiver's singleton class | whatever you pass | | `class_eval` / `module_eval` | `Module` | the module | the module itself | the module | | `class_exec` / `module_exec` | `Module` | the module | the module itself | whatever you pass | `class_eval` and `module_eval` are two names for one method; so are `class_exec` and `module_exec`. The `_eval` forms also accept a string of code; the `_exec` forms take only a block. ## instance_eval on a class Called on a class, both `Report.instance_eval` and `Report.class_eval` make `self` equal to `Report` — `Report.instance_eval { self }` and `Report.class_eval { self }` both return `Report`. The only difference is the definee: - `Report.instance_eval { def generate; end }` defines `generate` on `Report`'s **singleton class**, which is how Ruby stores class methods. You call it as `Report.generate`. - `Report.class_eval { def generate; end }` defines `generate` on **`Report`** itself, an instance method. You call it as `Report.new.generate`. The names look backwards at first. Read them as "evaluate as the instance `Report`" (a class is itself an object, and methods defined on one object are singleton methods) versus "evaluate as the body of class `Report`". On an ordinary object, `instance_eval` with a `def` inside gives that one object its own method; other instances of the class do not get it. `class_eval` is not available there at all: calling it on a non-module raises `NoMethodError`. ## Method calls follow self, not the definee Only the `def` keyword consults the default definee. Everything else is an ordinary method call on `self`: 1. `define_method(:footer) { ... }` inside `Report.instance_eval` is `Report.define_method(...)`, so it creates an **instance** method. 2. `attr_accessor :title` inside `Report.instance_eval` likewise creates `title` and `title=` for **instances** of `Report`. 3. `include SomeModule` inside `Report.instance_eval` is `Report.include(...)`, so the module's methods reach **instances**, not the class. This is the most common wrong answer at this level: a candidate learns "instance_eval on a class makes class methods" and then expects `attr_accessor` inside it to make class-level accessors. ## Choosing between them - **Adding instance methods to a class you hold in a variable** (a plugin, a generated class): `klass.class_eval` or `klass.class_exec`. - **Running a block against one object with its private state visible**, such as a configuration block on a builder: `instance_eval`, or `instance_exec` when the block needs arguments. - **Adding a class method**: `instance_eval` on the class works, but `define_singleton_method` or a `class << self` body state the intent more plainly. - **The block is a stored `Proc` written elsewhere** and needs values from the caller: an `_exec` variant, because the proc's closure cannot see the caller's locals. ## Mistakes to avoid - Saying `instance_eval` on a class defines instance methods because of its name. - Saying the two methods set `self` to different objects when called on a class. - Expecting `define_method` or `attr_accessor` inside `Report.instance_eval` to act on the class level. - Treating `module_eval` as different from `class_eval`. - Calling `class_eval` on a plain object to reach its class; use `obj.class.class_eval`, which changes every instance. ## The one-line model `self` decides where method calls and instance variables go; the default definee decides where `def` goes. `instance_eval` points the definee at the receiver's singleton class, `class_eval` points it at the module, and the `_exec` versions change only how arguments reach the block.

  • What do class_exec and instance_exec add over the _eval forms?
    They pass their arguments to the block as block parameters and accept only a block, not a string. That matters when the block is a stored `Proc` written somewhere else: its closure cannot see the caller's locals, so values have to arrive as arguments, as in `klass.class_exec(:period, &add_reader)`.
  • What happens if you call class_eval on an ordinary object such as Report.new?
    It raises `NoMethodError`, because `class_eval` and `module_eval` are defined on `Module`, and an ordinary object is not a module. To add a method to that one object, use `instance_eval` with a `def` inside; to change every instance, call `class_eval` on `obj.class`.

saying these in an interview costs you the question

  • instance_eval on a class defines instance methods, as its name suggests
  • class_eval and instance_eval set self to different objects on a class
  • define_method inside Report.instance_eval creates a class method
  • module_eval behaves differently from class_eval
  • class_eval can be called on any object to reach its class