Ruby Tip: Return Explicitly From Block
March 22, 2010
Sometimes when you use blocks you need to do something with the return value of a block. Using the last evaluated statement in the block can be hard to follow for others.
Consider the following trivial code. The actual scenario where I figured this out was much more complex and meaningful, of course.
def foo
10.times do |n| # We don't want to 'next' to this loop. Simply to prove a point.
"in loop #{n}"
puts return bar do |from_bar| # We want to return from this method in the first loop.
"got \"#{from_bar}\" from bar."
puts next "foo done" # This code will be the block's return value but will *not* apply to the outer loop.
end
end
end
def bar
"in bar"
puts yield "hello from bar"
ret = "back to bar land. got \"#{ret}\" from caller"
puts return "bar, signing out"
end
"foo returns \"#{foo}\"" puts
Here’s what you get when you run it:
in loop 0
in bar
got "hello from bar" from bar.
back to bar land. got "foo done" from caller
foo returns "bar, signing out"
This may be preferable to just putting your return value somewhere in the block whereit will evaluate last. If you’re building a complex block, first consider refactoring. If you can’t, you may want to use this ‘next’ trick. When you or someone works on the code later, they may not consider that the block must return a value, add some code at the end and completely throw off the intended return value.