๐ŸŽ“ A1Learner
๐Ÿ”
0 of 28 lessons completed

Ruby Instance Eval

instance_eval runs a block with one object as self inside the block. The block can then read and write the instance variables of that object directly.

Reading and writing private state

The block runs with the wallet as self. It reads the coins variable, adds five to it, and prints the new total.

class Wallet
  def initialize
    @coins = 10
  end
end
wallet = Wallet.new
wallet.instance_eval do
  puts @coins
  @coins = @coins + 5
  puts @coins
end

One block against two objects

The same block is stored once and run on two boxes. Each run answers with the label of the box it runs against.

class Box
  def initialize(label)
    @label = label
  end
end
red = Box.new "red"
blue = Box.new "blue"
show = proc { puts @label }
red.instance_eval(&show)
blue.instance_eval(&show)

Arguments with instance_exec

instance_exec hands its arguments to the block as parameters. The block adds them and stores the sum in the counter.

class Counter
  def initialize
    @count = 0
  end
end
counter = Counter.new
counter.instance_exec(3, 4) do |a, b|
  @count = a + b
  puts @count
end

The block value comes back

The block ends with the code variable, so instance_eval returns that string. The first run only prints the length of the code.

class Safe
  def initialize(code)
    @code = code
  end
end
safe = Safe.new "open-7"
safe.instance_eval do
  puts @code.length
end
puts safe.instance_eval { @code }

Example

class Thermostat
  def initialize
    @temp = 20
  end
end
unit = Thermostat.new
unit.instance_exec(5) do |step|
  @temp = @temp + step
end
puts unit.instance_eval { @temp }

Key points

  • instance_eval runs its block with the receiver as self.
  • The block reads and writes the instance variables of that object.
  • instance_exec passes arguments into the block it runs.
  • The same block gives a different answer on each object it runs against.
  • instance_eval returns the last value of its block.

In this example, instance_exec runs its block with the thermostat as self and passes 5 in as the step. The block raises the stored temperature by that step. A short instance_eval block then reads the temperature back, and the program prints 25.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

What does counter.instance_exec(2, 6) { |a, b| a + b } return?