Download this source

# This is a method, with a block parameter.
def other_method(a, &b)
  b.call(a)
end

# Call the block method
other_method("Copeco") { | a | puts "Hello there #{a}" }
other_method(28) { | a | puts a * 10 }

# Ruby blocks are true closures - they capture the scope they're defined in.
multiplier = 20
other_method(5) { | a | puts a * multiplier }

# As well as passing blocks in a method call, we can also predef a closure
# with 'lambda', which makes an instance of Proc. You may also see 'proc' 
# referred to (as a method) but you should probably prefer the 'lambda' keyword.
square = lambda { | i | puts i * i }

# You must use & to pass predefined, since the method actually expects only 
# one arg (the &block argument isn't counted - it means 'the block that's
# attached to the call').
other_method(10,&square)

# So blocks are used to implement coroutines, where a method and block defined
# separately work together for a common goal. This is how a lot of the Ruby API
# (things like each_whatever, inject, etc, etc, etc) is done.

# Much of the time, if you're just going to be calling the block, you don't
# need to bother with a &argument - you can just call 'yield' to pass control
# to the block supplied to the method.
def block_method(text)
  yield ">>>" + text + "<<<" if text != nil
  yield ">>>" + text + "<<<" if text != nil
end

# So it's basically the same as the closure blocks, except that the 
# block argument is implied. The arguments to 'yield' are passed to the block.
# You may need to check if you're given a block, which can be done with:

def careful_block_method
  if block_given?
    yield self
  else
    puts "Where's the block?"
  end
end

# The following call will print >>>Hello<<< twice. 
block_method("Hello") { | it | puts it }

# Does nothing
careful_block_method

Running this outputs:

Hello there Copeco
280
100
100
>>>Hello<<<
>>>Hello<<<
Where's the block?