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?

Original source