There are two common styles for choosing do end
vs. { }
for blocks in Ruby:
The first and very common style was popularized by Ruby on Rails, and is based on a simple rule of single vs. multi-line:
- Use braces
{ }
for single-line blocks
- Use
do end
for multi-line blocks
This makes sense because do/end reads badly in a one-liner, but for multi-line blocks, leaving a closing }
hanging on its own line is inconsistent with everything else that uses end
in ruby, such as module, class & method definitions (def
etc.) and control structures (if
, while
, case
, etc.)
The second, less-frequently seen style is known as semantic, or "Weirich Braces", proposed by the late, great rubyist Jim Weirich:
- Use
do end
for procedural blocks
- Use braces
{ }
for functional blocks
This means that when the block is evaluated for its return value, it should be chainable, and the {}
braces make more sense for method chaining.
On the other hand, when the block is evaluated for its side-effects, then the return value is of no consequence, and the block is just "doing" something, so it does not make sense to be chained.
This distinction in the syntax conveys visual meaning about the evaluation of the block, and whether or not you should care about its return value.
For example, here the return value of the block is applied to every item:
items.map { |i| i.upcase }
However, here it's not using the block's return value. It's operating procedurally, and doing a side-effect with it:
items.each do |item|
puts item
end
Another benefit of the semantic style is that you don't need to change braces to do/end just because a line was added to the block.
As an observation, coincidentally functional blocks are frequently a one-liner, and procedural blocks (e.g. config) are multi-line. So, following the Weirich style ends up looking almost the same as the Rails style.