Should I use instance_eval or class_eval?
Tags: ruby
Published: 2021-02-06 20:41:38

---
title: Should I use instance_eval or class_eval?
published: true
date: 2021-02-02 00:00:00 UTC
tags: ruby
canonical_url: https://daniel-azuma.com/blog/2021/02/02/should-i-use-instance-eval-or-class-eval
---

Ruby objects have methods called `instance_eval` and `class_eval`. They both execute a block with `self` referencing the object.

```
class C; end

C.instance_eval { puts "instance_eval: self = #{self}" }
# prints "instance_eval: self = C"

C.class_eval { puts "class_eval: self = #{self}" }
# prints "class_eval: self = C"
```

For a long time I thought these methods were basically synonymous, that for some reason I was simply supposed to use `class_eval` for classes (and `module_eval` for modules) and `instance_eval` for everything else. Just accept it and don’t ask questions, I told myself.

But there _is_ a difference, one that points to an important but seldom understood aspect of Ruby. In this article, we’ll explore the distinction and what it means for our Ruby code.

## The “current object”

Let’s start with what many Ruby programmers already know.

Like many object-oriented languages, Ruby has the notion of a “current object”. This is the object that receives method calls by default, and it is the object that owns any instance variables you reference. Ruby sets the current object inside every method call, so the method can access the object’s instance variables and easily call other methods of the object.

```
class Greeter
  def initialize(name)
    @name = name
  end

  def greeting
    # Reference "@name" from the current object
    "Hello, #{@name}!"
  end

  def print_greeting
    # Call the "greeting" method in the current object
    puts greeting
  end
end
```

You can get a reference to the current object using the `self` keyword, but for the most part, it’s used implicitly when resolving methods or instance variables.

There is always a current object, even when you’re not in a method. Within a class definition, the current object is the class. And Ruby even provides a “main” object that is the current object at the top level of a Ruby script.

```
class Greeter
  puts self
  # Prints "Greeter"
end

puts self
# Prints "main"
```

## Changing the current object with instance\_eval

You can also _change_ the current object using the `instance_eval` method (or the closely related `instance_exec`).

```
greet = Greeter.new("world")

# Change the object context within the given block.
greet.instance_eval do
  # Self now references the greeter object
  assert self == greet

  # You can call its methods without a receiver
  print_greeting

  # You can even access its instance variables
  puts @name
end
```

The `instance_eval` method is commonly used for building domain-specific-languages (DSLs) because it lets us control how methods are looked up. When you write [Rails routes](https://guides.rubyonrails.org/routing.html), for example, Rails is using `instance_eval` to give you a simple syntax for declaring paths and resources.

The current object has a strong effect on looking up method names, but what about _defining_ a method? This is where the story gets a bit more complicated.

## Defining methods

The `def` keyword is typically used to define a new method. Normally, `def` appears within a class or module definition, so it’s clear where the method is defined. But Ruby is very flexible. You can put a `def` almost anywhere: outside any class, in a block, even within another method.

What do you think happens when a method is defined inside another method?

```
class Greeter
  def greeting
    def dismissal
      "Bye, world!"
    end
    "Hello, world!"
  end
end
```

No, Ruby doesn’t have any weird notion of “nested” methods. All that’s happening here is that defining the `dismissal` method is part of the _functionality_ of the `greeting` method. `dismissal` is defined when you _call_ `greeting`.

So what class is `dismissal` defined on? One might guess that it’s also defined on the `Greeter` class, and in this case you’d be right. But _why_ is that the case? It may seem “obvious” or “intuitive,” but it’s very important to understand what’s actually going on, because things won’t always be obvious. Take this example:

```
class Greeter
  def greeting
    "Hello, world!"
  end
end

Greeter.instance_eval do
  def dismissal
    "Bye, world!"
  end
end
```

We’re using `instance_eval` to set the object context to the `Greeter` class when we define the method. So where is `dismissal` defined? You might guess, on the `Greeter` class. But you’d be wrong. It gets defined on the `Object` class.

So what’s really going on? What actually governs on which class a method is defined?

## The “current class”

The answer is that “self” isn’t the only piece of context that Ruby maintains. The “current object” governs lookup of method names (and instance variables), but method _definitions_ are governed by a separate piece of context that I’ll call the “current class”.

> Note: other terms have been used elsewhere for the “current class”. For example, Yugui used the term “default definee” when she wrote about the Ruby contexts in an [earlier article](https://blog.yugui.jp/entry/846).

When you define a class using the `class` keyword, it creates a class and sets the current class context so that methods are attached to it. Similarly, when a method is called, the current class context is set to `self`’s class.

```
class Greeter
  # Current class is set to Greeter.
  # This ensures the greeting method is defined on Greeter.
  def greeting
    # Current class is set to self's class, which is Greeter.
    # This ensures the dismissal method is also defind on Greeter.
    def dismissal
      "Bye, world!"
    end
    "Hello, world!"
  end
end
```

However, importantly, `instance_eval` sets the current object but _not_ the current class.

```
# Current class is Object at the top level of a Ruby file

Greeter.instance_eval do
  # The instance_eval method sets self but not the current class,
  # so the current class is still Object here.
  def dismissal
    "Bye, world!"
  end
end
```

And this is where `class_eval` is different. Whereas `instance_eval` sets _only_ the current object, `class_eval` sets _both_ the current object and current class.

```
Greeter.class_eval do
  # The current class is now Greeter.
  def dismissal
    "Bye, world!"
  end
end
```

So we’ve seen that Ruby maintains _separate, independent_ class and object contexts. And that brings up an interesting question: Why?

## Why are “current class” and “current object” distinct?

Why maintain two separate pieces of state? Isn’t that needlessly complicated?

It turns out there’s a good reason for it, and it has to do with Ruby’s goal of making programming intuitive. Let’s look again at the two places we’ve seen method definitions.

When you use a `class` declaration, Ruby sets both the current object and the current class to the same thing, the class. This lets you both define methods and call class methods such as `attr_reader`, `include`, and even `private`.

```
class Greeter
  # current class == self
  # This means you can define methods on the class
  def greeting
    "Hello, world!"
  end

  # And you can also call class methods
  attr_reader :language
end
```

But when you define a method in another method, the current object and the current class are _not_ the same. An arbitrary object doesn’t have methods; only classes do. So the current class is set to the class of the object.

```
class Greeter
  def greeting
    # current class != self
    # current class == self.class
    def dismissal
      "Bye, world!"
    end
    "Hello, world!"
  end
end
```

In order to support reasonable behavior in both of these two cases, Ruby needs the flexibility to be able to set up the two values, current object and current class, differently.

## Why does this matter?

So Ruby has more context than just `self`. Why does it matter?

Well, it might help you avoid some bugs, and it’s always useful to understand the details of the language you are using. But it’s particularly important when you are designing interfaces for other developers to use, especially if you’re designing a domain-specific language.

Ruby is a flexible language, and Ruby programmers expect to be able to use that flexibility, calling code, writing helper methods, and generally doing things you might not expect. If the Rails router had set the current class to some strange value and made it difficult for users to write helper methods, Rails would have been much more brittle and difficult to use, and ultimately less successful.

So it’s important for Ruby library writers to make sure you choose the correct method when using `class_eval` or `instance_eval`. And in general, library designers need to pay attention to the current class in order to avoid unexpected behavior.

If you’re interested in learning some tips for designing interfaces that pay attention to these issues, see my talk [“Ruby Ate My DSL!”](https://www.youtube.com/watch?v=Ov-tMtOkKS4) from RubyConf 2019.

## Investigating further

It turns out, the rabbit hole goes even deeper. A third independent piece of Ruby context governs constants, where they are defined and how they are looked up. This piece of context, known internally as the `cref`, represents the lexical nesting of classes and modules, basically what you get from calling `Module.nesting`. However, unlike the current object and current class, the cref can’t be changed programmatically, at least not without dropping into C.

```
class Greeter
  # The cref points to Greeter, so GREETING is defined there
  GREETING = "hello"
end

puts Greeter::GREETING
# prints "hello"

Greeter.class_eval do
  # class_eval doesn't affect cref, so SALUTATION is defined on Object
  SALUTATION = "hi"
end

puts Object::SALUTATION
# prints "hi"

puts Greeter::SALUTATION
# Raises NameError
```

Because cref can’t be modified from Ruby, it’s difficult to control how constants are defined and managed in DSLs. This is generally why many DSLs eschew constants or provide alternatives.

And indeed, there are several other elements to the Ruby “context”, controlling such functionality as what `super` calls, how iteration keywords like `next` and `break` behave, and so forth. If you’re interested in exploring this further, the old Ruby hacking guide has [a chapter](https://ruby-hacking-guide.github.io/module.html) dedicated to the context, but it’s from the Ruby 1.7 era and might be out of date. Pat Shaughnessy’s excellent book [_Ruby Under a Microsocope_](http://patshaughnessy.net/ruby-under-a-microscope) is somewhat newer and also covers some of these topics. (If anyone knows of other resources, leave a note in the comments!)