idiosyncratic_eval

When you get farther upwards the steep hill that is Ruby mastery, you will come across some powerful, yet slightly evil methods: instance_eval and class_eval¹. They allow you to execute code and define methods tied to a specific class, at the same time giving you access to outer scope variables through the Ruby block syntax. Their exact behavior varies, depending on the context they are used in. So what is the difference between all the evals?

¹ Also aliased as module_eval

Eval / Method Definition Comparison

In the following tables, you will find all combinations of defining a method and executing it in a different class context:

Class Scope

Definition Method No eval class_eval instance_eval
def instance instance class
define_method instance instance instance
def self. class class class
define_singleton_method class class class

Class-Class Scope (class << self)

Definition Method No eval class_eval instance_eval
def class class class-class
define_method class class class
def self. class-class class-class class-class
define_singleton_method class-class class-class class-class

Observations

While class_eval behaves exactly as if it was in no eval-context at all, instance_eval features a notable difference: def inside instance_eval will define methods one class-level higher. So when instance_eval is executed on instances, def will create instance methods instead of singleton methods. And when it is run on classes, def will create class methods instead of instance methods.

Another difference is that while class_eval is defined on Module, instance_eval lives in BasicObject allowing you to use it on any object, not only modules and classes. However, there is a simple way to use class_eval for instances, too. You can explicitly use the object's singleton class (class << self), which is a module:

o = Object.new # => #<Object:0x000055b6fdabf1f8>
o.singleton_class.class_eval do
  def m
    p self
  end
end

o.m # => #<Object:0x000055b6fdabf1f8>

Best Practice

Overall, the behavior of instance_eval is rather confusing and my recommendation is to avoid it and always use class_eval. If you do not need closure access, consider using no eval at all.

Reference / Examples: Class-Level Scope

For reference, what follows is a list of snippets illustrating each eval-define combination.

Class / def

Defines method on instance-level

class C
  def m
    p self
  end
end

C.new.m # => #<C:0x0000556efd3eb1a8>

Class / class_eval + def

Defines method on instance-level

class C
  class_eval{
    def m
      p self
    end
  }
end

C.new.m # => #<C:0x0000556efd3eb1a8>

Class / instance_eval + def

Defines method on class-level

class C
  instance_eval{
    def m
      p self
    end
  }
end

C.m # => C

Class / define_method

Defines method on instance-level

class C
  define_method(:m){
    p self
  }
end

C.new.m # => #<C:0x0000556efd3eb1a8>

Class / class_eval + define_method

Defines method on instance-level

class C
  class_eval{
    define_method(:m){
      p self
    }
  }
end

C.new.m # => #<C:0x0000556efd3eb1a8>

Class / instance_eval + define_method

Defines method on instance-level

class C
  instance_eval{
    define_method(:m){
      p self
    }
  }
end

C.new.m # => #<C:0x0000556efd3eb1a8>

Class / def self.

Defines method on class-level

class C
  def self.m
    p self
  end
end

C.m # => C

Class / class_eval + def self.

Defines method on class-level

class C
  class_eval{
    def self.m
      p self
    end
  }
end

C.m # => C

Class / instance_eval + def self.

Defines method on class-level

class C
  instance_eval{
    def self.m
      p self
    end
  }
end

C.m # => C

Class / define_singleton_method

Defines method on class-level

class C
  define_singleton_method(:m){
    p self
  }
end

C.m # => C

Class / class_eval + define_singleton_method

Defines method on class-level

class C
  class_eval{
    define_singleton_method(:m){
      p self
    }
  }
end

C.m # => C

Class / instance_eval + define_singleton_method

Defines method on class-level

class C
  instance_eval{
    define_singleton_method(:m){
      p self
    }
  }
end

C.m # => C

Reference / Examples: Class-Class-Level Scope

Class-Class / def

Defines method on class-level

class C
  class << self
    def m
      p self
    end
  end
end

C.m # => C

Class-Class / class_eval + def

Defines method on class-level

class C
  class << self
    class_eval{
      def m
        p self
      end
    }
  end
end

C.m # => C

Class-Class / instance_eval + def

Defines method on class-class-level

class C
  class << self
    instance_eval{
      def m
        p self
      end
    }
  end
end

C.singleton_class.m #=> #<Class:C>

Class-Class / define_method

Defines method on class-level

class C
  class << self
    define_method(:m){
      p self
    }
  end
end

C.m # => C

Class-Class / class_eval + define_method

Defines method on class-level

class C
  class << self
    class_eval{
      define_method(:m){
        p self
      }
    }
  end
end

C.m # => C

Class-Class / instance_eval + define_method

Defines method on class-level

class C
  class << self
    instance_eval{
      define_method(:m){
        p self
      }
    }
  end
end

C.m # => C

Class-Class / def self.

Defines method on class-class-level

class C
  class << self
    def self.m
      p self
    end
  end
end

C.singleton_class.m # => C

Class-Class / class_eval + def self.

Defines method on class-class-level

class C
  class << self
    class_eval{
      def self.m
        p self
      end
    end
  }
end

C.singleton_class.m #=> #<Class:C>

Class-Class / instance_eval + def self.

Defines method on class-class-level

class C
  class << self
    instance_eval{
      def self.m
        p self
      end
    }
  end
end

C.singleton_class.m #=> #<Class:C>

Class-Class / define_singleton_method

Defines method on class-class-level

class C
  class << self
    define_singleton_method(:m){
      p self
    }
  end
end

C.singleton_class.m # => C

Class-Class / class_eval + define_singleton_method

Defines method on class-class-level

class C
  class << self
    class_eval{
      define_singleton_method(:m){
        p self
      }
    }
  end
end

C.singleton_class.m #=> #<Class:C>

Class-Class / instance_eval + define_singleton_method

Defines method on class-class-level

class C
  class << self
    instance_eval{
      define_singleton_method(:m){
        p self
      }
    }
  end
end

C.singleton_class.m #=> #<Class:C>

Also See

More Idiosyncratic Ruby