Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call a ruby block to get access to the caller bindings

I want to have access to the bindings of the caller. What's wrong here?

require 'test/unit'

class BlocksTest < Test::Unit::TestCase

  class Blocks
    def initialize( &block ); @block = block; end
    def run; instance_eval { @block.call }; end

    def foo; 'foo'; end
  end

  def test_say_foo_via_string
    assert_equal( 'foo', Blocks.new{ 'foo' }.run )
  end
  # => successful

  def test_say_foo_via_caller_method
    assert_equal( 'foo', Blocks.new{ foo }.run )
  end
  # => NameError: undefined local variable or method `foo'

end

Why i don't have access to the caller instance within the given block?

like image 305
sschmeck Avatar asked Jul 01 '13 08:07

sschmeck


1 Answers

Inside the block you are not in the scope of the Blocks instance, so foo is not visible. You have to pass the object to the block if you want to have access to it:

class Blocks
  # ...
  def run
    @block.call(self)
  end
  # ...
end

blk = Blocks.new { |b| b.foo }
blk.run
# => "foo"

Alternatively you can pass the block to instance_eval:

class Blocks
  # ...
  def run
    instance_eval(&@block)
  end
  # ...
end

blk = Blocks.new { foo }
blk.run
# => "foo"
like image 176
toro2k Avatar answered Oct 13 '22 19:10

toro2k