Why doesn't `block_given?` work in this dynamically-defined method?
ruby, ruby-1.9, ruby-1.9.3
Solution
Blocks are closures, so they remember local variables (eg `method_name`). They also remember blocks: `yield` and `block_given?` are looking for the block that was active at the time that `define_method` was called, not the block passed to `bar`. There wasn't one, so block given returns false.
A better illustration of this is
def create_method
define_singleton_method('foo') do |&block|
puts "Was given a block? #{block_given?}"
puts yield
puts block.call
end
end
create_method {'block passed to create_method'}
foo {'block passed to the created method'}
which outputs
Was given a block? true
block passed to create_method
block passed to the created method
Problem
When I write methods that take an optional block, I typically use something like ``` block.call if block_given? ``` However, in method defined dynamically like the one below, `block_given?` doesn't seem to work. ``` class Foo %w[bar baz].each do |method_name| define_singleton_method(method_name) do |&block| puts "Was #{method_name} given a block? #{block_given?}" puts block.call end end end Foo.bar { puts 'I am a block' } ``` The block is called as expected, but `block_given?` returns false. Why is this?