Ruby tries to add a spoon of sugar to each damn line of your code any time she thinks it to be possible. That’s nice. Sometimes she became meddlesome. That used to drive me bonkers. A newbie is to be that rara avis, to understand that there is actually a huge difference between braces and do-end constructs to define a block.

Well, everybody may spend a life successfully writing tons lines of ruby code and never get stuck in weird exceptions, coming from 3rd party libs, which in case were induced by negligent mess between {} and do-end in domestic code. Let’s digress from our dramatic story and take a look at the following snippet. Somebody was set bringing benchmarks to an application running at a snail’s pace. Well, the task looks straightforward. Install benchmark gem, read the documentation, try an example:

require 'benchmark'
puts Benchmark.measure { "a"*1_000_000 }

Works fine! Let’s try smth more complicated:

require 'benchmark'
puts Benchmark.measure do
  while true
    print 'a'
    break if Random.rand(100) === 1
  end
end

Ooooups…

irb:010 >
# LocalJumpError: no block given (yield)
#     from IRRELEVANT_PATH_TO_RVM/lib/ruby/2.0.0/benchmark.rb:281:in `measure'
#     from (irb):9`

WTF? That’s the syntax sugar, ruby mixed into your tea. That’s a time to take a look at an operator precedence table. {} binds tighter than do-end. Furthermore, do-end clause has lowest precedence at all. In other words, the latter codepiece is similar to:

require 'benchmark'
(puts Benchmark.measure) do
  # irrelevant code
end

Surely, the aforementioned hitch never befuddled a guru, but there is a style guideline which may get rid of the possibility even to stuck with this. Use braces {} when a block returnes a value. Use do-end clause otherwise.