Rubyにしては珍しく

混乱してしまうところ。

Rubyはブロックを記述する際に、その範囲を示すトークンとしてdo〜endとブレース({〜})のどちらでも使える。

メソッド呼び出し do
  ブロック
end

メソッド呼び出し {
  ブロック
}

ブロックを表す書き方としては同じだが、両者には結合度(優先度)の違いがあるため、以下のように括弧を省略してメソッド呼出を行うと、意味が変わってしまうことがある。

  • blockprior.rb
def foo(bar)
  if block_given?
    puts yield
  else
    puts bar
  end
end

bar = "バー"
foo bar do "ブロック" end

bar = "バー"
foo bar { "ブロック" }
  • 実行結果
>ruby blockprior.rb
ブロック
blockprior.rb:13: undefined method `bar' for main:Object (NoMethodError)

2度めのfooメソッドの呼び出し時、ブレースを使うことでブロックがbarと結合してしまい、エラーとなってしまう。
ならばdo〜endだけを使えばよいかと思えば、以下のようにブレースを使わなくてはならないケースもある。

irb(main):001:0> puts [1, 2, 3, 4, 5].inject { |a, b| a+b }
15
=> nil
irb(main):002:0> puts [1, 2, 3, 4, 5].inject do |a, b| a+b end
LocalJumpError: no block given
        from (irb):2:in `inject'
        from (irb):2:in `each'
        from (irb):2:in `inject'
        from (irb):2

do〜endを使った場合はinjectに結合できないためにエラーになってしまう。

この辺の使い分けを意識的に出来るようにならないと初心者からは脱却できないな。