I’m just learning ruby and trying to understand the scope of code executed in blocks. For example, I want to be able to create a block that affects the method that it is attached to, like so:
def test(&block) block.call() if block_given? puts 'in test, foo is #{foo}' puts 'in test, bar is #{bar}' end test() { foo='this is foo' bar='this is bar' }
In this case I don’t want to have to modify the block at all — I want to be able to write it using simple variable references and no parameters. Only by making changes to the ‘test’ method in the above example, is it possible to access the variables defined in the block?
Again, the goal is to leave the block unmodified, but be able to access the created variables from within ‘test’ after the block executes.
First of all,
block.call()is done withyield, and you don’t need the&blockparameter that way.You can’t normally do what you want, blocks are bound when they are created, and inside the block you can see the local variables defined at that moment; the easiest way to do what you want, which is not how you will use blocks normally, is this:
But that’s only a side effect because
foois ‘returned’ by the block. If you instead do this:You’ll notice that it does something different.
Here’s more magic:
That would kind of work, but it breaks if you remove
foo = 'before test'becausefoobecomes a local variable in the block and does not exist in the binding.Summary: you can’t access local variables from a block, just the locals where the block was defined and the return value of the block.
Even this won’t work:
because the
fooin the binding is different from the local in the block (I didn’t know this, thanks).