As a dynamic script language, Ruby provides a few different options to evaluate a string or a block of code: eval, class_eval, module_eval, and instance_eval. What is the difference between them? This article describes it well. The main different is the context: instance_eval evaluates in the context of a certain instance, module_eval (and class_eval) in the context of a class, and eval in the current context or the context of the given binding.

instance_eval

Object.instance_eval evaluates a string (or the given block) within the context of a certain class instance and allows thus the direct access to class properties without attr or attr_accessor. It allows you to define new methods for a instance

class Klass
  def initialize
    @secret = 99
  end
end
k = Klass.new
k.instance_eval("@secret")    # => "99"
k.instance_eval("@secret=42") # => "42"

k.instance_eval("def hi() \"Hello there\" end")
k.hi()  # => "Hello there"

eval

Kernel.eval evaluates a string in the current context or the context of the given binding. It is the method used by IRB to process your input. It allows you to define new variables and methods for the current context.

def secret(number)
  return binding
end
number = "42"
eval "number"                #=> "42"
eval "number", secret("99")  #=> "99"

eval "def hi() \"Hello there\" end"
hi()  # => "Hello there"

module_eval

As the name says, Module.module_eval evaluates the string or block in the context of a module or class (Synonym: class_eval). module_eval allows you to define new instance method for a class.

String.module_eval do
  def secret
    "42"
  end
end

"string".secret    #=> "42"
Advertisements