Using instance_exec to change block scope

When you create a block in Ruby and execute it later it’s context is tied to where it was defined. Take a look at this very contrived example:

class Dog
  attr_accessor :name, :block

  def initialize(name)
    @name = name
    @block = proc do
      puts "#{self.name} the #{self.class.name}"
    end
  end
end

class Person
  attr_accessor :name, :block

  def initialize(name)
    @name = name
  end
end

@fido = Dog.new('Fido')
@mark = Person.new('Mark')
@mark.block = @fido.block

If you load the code above into irb or pry you can see this in action:

[2] pry(main)> @mark.block.call
Fido the Dog
=> nil

In the block self refers to @fido, the instance of the Dog class in which the block was defined. If you want to execute the block in the context of another object you can use instance_exec like so:

[3] pry(main)> @mark.instance_exec(&@fido.block)
Mark the Person
=> nil

You can find the documentation of instance_exec here.