4

I just wanted to use a heredoc as a value in a hash literal. While it works fine if the heredoc is the very last element:

{
  foo: 123,
  bar: <<-HEREDOC
    a longer text
  HEREDOC
}
#=> {:foo=>123, :bar=>"    a longer text\n"}

I couldn't find a way to add another key-value pair after the heredoc. Or, more specifically, I couldn't find a way to insert the separating comma without causing a syntax error:

{
  foo: 123,
  bar: <<-HEREDOC
    a longer text
  HEREDOC
  # <- causes a syntax error because a comma is missing here, but where to put it?
  baz: 456
}
Stefan
  • 109,145
  • 14
  • 143
  • 218
  • you might need to remove leading whitespace as well - http://stackoverflow.com/questions/3772864/how-do-i-remove-leading-whitespace-chars-from-ruby-heredoc – max pleaner Oct 29 '16 at 17:35

2 Answers2

10

This seems to work

{
  foo: 123,
  bar: <<-HEREDOC,
    a longer text
  HEREDOC
  baz: 456
}
Ursus
  • 29,643
  • 3
  • 33
  • 50
4

Ursus' answer is spot on. The reason why this works is that the heredoc doesn't start immediately after the opening identifier, but on the line following the opening identifier. Everything after the opening identifier (on the same line) is parsed as usual.

This not only allows you to put the , right after the <<-HEREDOC, it allows you to define the entire hash in one line:

{ foo: 123, bar: <<-HEREDOC, baz: 456 }
  a longer text
HEREDOC
#=> {:foo=>123, :bar=>"      a longer text\n", :baz=>456}

You could also pass two heredocs: (using ~ instead of - strips whitespace)

{ foo: 123, bar: <<~BAR, baz: <<~BAZ }
  bar's value
BAR
  baz's value
BAZ
#=> {:foo=>123, :bar=>"bar's value\n", :baz=>"baz's value\n"}

Ruby's heredoc documentation contains similar examples, but unfortunately RDoc doesn't get it right, so they are often overlooked:

To call a method on a heredoc place it after the opening identifier:

expected_result = <<-EXPECTED.chomp
One plus one is #{1 + 1}  
EXPECTED

You may open multiple heredocs on the same line, but this can be difficult to read:

 puts(<<-ONE, <<-TWO)
 content for heredoc one
 ONE
 content for
 heredoc two
 TWO
Community
  • 1
  • 1
Stefan
  • 109,145
  • 14
  • 143
  • 218