Thinking about yield(self)
(by Erik Peterson on April 10th 2008)

Maybe my brain is broken, but when using blocks in Ruby, I keep wanting to have access to the scope of the calling object:

class Foo
  def bar
    baz = "qux"
    yield
  end
end

>> Foo.new.bar { puts baz }
NameError: undefined local variable or method 'baz' for main:Object

Which makes sense, of course. But what if I really needed to know what baz was, in the context of the block? (Assume that I'm determining my accessing needs at runtime, and can't add arguments willy-nilly to the yield call). The solution I came up with was to use yield(self). It seems kind of dirty, and it is- but it works. Mostly.

class Foo
  attr_accessor :accessible_baz
  def bar
    baz = "qux"
    @instance_baz = "qux"
    @accessible_baz = "qux"
    yield(self)
  end
end

#Attempt to get the local variable
>> Foo.new.bar {|container| puts container.baz }
NameError: undefined local variable or method 'baz' for main:Object

#Attempt to get an instance variable without an accessor
>> Foo.new.bar {|container| puts container.instance_baz }
NoMethodError: undefined method 'instance_baz' for #
>> Foo.new.bar {|container| puts container.instance_variable_get(:@instance_baz) }
qux

#Attempt to get an instance variable with an accessor
>> Foo.new.bar {|container| puts container.accessible_baz }
qux

I think this might be an OK solution if you're just trying to get at methods or accessible instance variables of the calling object, but I'm not sure it is worth it to go through instance_variable_get in order to get other instance variables. Is there a better way to get at this stuff? Any method that is more elegant?