---
title: "instance_exec , changing self and params"
description:
  "instance_exec could be confusing. It can be used to change self. This blog
  discusses how to use instance_exec."
canonical_url: "https://www.bigbinary.com/blog/instance-exec-changing-self-and-parameters-to-proc"
markdown_url: "https://www.bigbinary.com/blog/instance-exec-changing-self-and-parameters-to-proc.md"
---

# instance_exec , changing self and params

instance_exec could be confusing. It can be used to change self. This blog
discusses how to use instance_exec.

- Author: Neeraj Singh
- Published: May 28, 2010
- Categories: Ruby

_Here is
[updated article on the same topic](understanding-instance-exec-in-ruby) ._

Following code will print `99` as the output.

```ruby
class Klass
  def initialize
    @secret = 99
  end
end
puts Klass.new.instance_eval { @secret }
```

Nothing great there. However try passing a parameter to `instance_eval` .

```ruby
puts Klass.new.instance_eval(self) { @secret }
```

You will get following error.

```ruby
wrong number of arguments (1 for 0)
```

So `instance_eval` does not allow you to pass parameters to a block.

## How to get around to the restriction that instance_eval does not accept parameters

`instance_exec` was added to ruby 1.9 and it allows you to pass parameters to a
proc. This feature has been backported to ruby 1.8.7 so we don't really need
ruby 1.9 to test this feature. Try this.

```ruby
class Klass
  def initialize
    @secret = 99
  end
end
puts Klass.new.instance_exec('secret') { |t| eval"@#{t}" }
```

Above code works. So now we can pass parameters to block. Good.

## Changing value of self

Another feature of `instance_exec` is that it changes the value of `self`. To
illustrate that I need to give a longer example.

```ruby
module Kernel
  def singleton_class
    class << self
      self
    end
  end
end

class Human
  proc = lambda { puts 'proc says my class is ' + self.name.to_s }

  singleton_class.instance_eval do
    define_method(:lab)  do
      proc.call
    end
  end
end

class Developer < Human
end

Human.lab # class is Human
Developer.lab # class is Human ; oops
```

Notice that in that above case `Developer.lab` says "Human". And that is the
right answer from ruby perspective. However that is not what I intended. ruby
stores the binding of the proc in the context it was created and hence it
rightly reports that self is "Human" even though it is being called by
`Developer`.

Go to
[http://facets.rubyforge.org/apidoc/api/core/index.html](http://facets.rubyforge.org/apidoc/api/core/index.html)
and look for `instance_exec` method. The doc says

<blockquote>
  Evaluate the block with the given arguments within the context of this object,
  so self is set to the method receiver.
</blockquote>

It means that `instance_exec` evaluates self in a new context. Now try the same
code with `instance_exec` .

```ruby
module Kernel
  def singleton_class
    class << self
      self
    end
  end
end

class Human
  proc = lambda { puts 'proc says my class is ' + self.name.to_s }

  singleton_class.instance_eval do
    define_method(:lab)  do
      self.instance_exec &proc
    end
  end
end

class Developer < Human
end

Human.lab # class is Human
Developer.lab # class is Developer
```

In this case `Developer.lab` says `Developer` and not `Human`.

You can also checkout this page (Link is not available) which has much more
detailed explanation of `instance_exec` and also emphasizes that `instance_exec`
does pass a new value of `self` .

`instance_exec` is so useful that `ActiveSupport` needs it. And since ruby 1.8.6
does not have it `ActiveSupport` has code to support it.

I came across `instance_exec` issue while resolving
[#4507 rails ticket](https://rails.lighthouseapp.com/projects/8994/tickets/4507)
. The final solution did not need `instance_exec` but I learned a bit about it.

## Links

- [Human page](https://www.bigbinary.com/blog/instance-exec-changing-self-and-parameters-to-proc)
