Blocks are closures, so they remember local variables (for example, method_name). They also memorize blocks: yieldand block_given?look for the block that was active at the time of the call define_method, and not the block passed to bar. There were none, so this block returns false.
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'}
Was given a block? true
block passed to create_method
block passed to the created method