Code block passed to each works with brackets but not with 'do'-'end' (ruby)

I recently started learning ruby, and I understood that you coud use code blocks with both of these syntaxes. But I just found a case which I dont understand:

#my_hash is a hash in which the keys are strings and the values arrays, but dont think about the specifics fo the code

#if I run my code like this, it works perfectly

my_hash.each do |art|
  puts mystring.gsub(art[0]).each {
    art[1][rand(art[1].length) -1]
  }
end

#but if I use this, it prints "Enumerator"

my_hash.each do |art|
  puts mystring.gsub(art[0]).each do
    art[1][rand(art[1].length) -1]
  end
end

Is it because you cant nest do-end pairs? I am using 1.9


puts mystring.gsub(art[0]).each do
  art[1][rand(art[1].length) -1]
end

Here you called puts without parens, the do ... end refers to the puts method, that does nothing with a block and prints mystring.gsub(art[0]).each (with is a Enumerator).

The { ... } is called with the nearest method. Becomes ugly, but you can do it with do ... end:

puts(mystring.gsub(art[0]).each do
  art[1][rand(art[1].length) -1]
end)

Or, better, put the result in a variable and print the variable:

var = mystring.gsub(art[0]).each do
  art[1][rand(art[1].length) -1]
end
puts var

Anyway, the each don't changes the object, it just iterate and returns the object itself. You may be wanting the map method, test it.


Expanding on Scott's reply, and quoting Jim Weirich:

The difference is where in the operator precedence table they fall. { } binds tighter than do/end. For example:

f g { }

is parsed as f(g { }), where the braces belong to the method g. On the other hand,

f g do end

is parsed as f(g) do end, where the braces belong to the method f. It only matters when you omit parenthesis and create ambiguities.