Using heredoc for prettier Ruby code

You can use heredoc Archive to avoid endlessly long lines of code that nobody can read. Heredoc strings preserve linebreaks and can be used like this:

def long_message
  puts(<<-EOT)
    Here goes a very long message...
    Sincerely,
    foobear
  EOT
end

<<-EOT will be somewhat of a placeholder: anything you write in the line after you used it will be its value until you write EOT in a single line.

You can use any string to flag your heredocs. To be more verbose you can use something else -- your IDE may even be aware of it, for example RubyMine understands <<-SQL, <<-HTML, <<-XML, <<-JSON, etc and highlights correctly.

Please note:

  • Your string will end with a new-line character (\n).

  • Your string's lines will be padded with its indentation. The string from the example above will be " Here goes a very long message...\n Sincerely,\n foobear\n". Depending on where you use it, this may or may not be a problem. A possible solution is <<~ (see below).

  • You can use regular string interpolation inside heredoc strings:

    puts <<-TEXT
      Dear #{user.name},
      ...
    TEXT
    
  • Your statement does not have to terminate after the placeholder. Example:

    content_tag(:div, <<-TEXT, class: 'example')
      Dear #{user.name},
      ...
    TEXT
    

<<~ vs <<-

You can use <<~ (with a tilde) to remove the string's indentation. This will keep any relative indentation in other lines.

<<~TEXT
  Hello
  Universe!
    -foo
TEXT
# => "Hello\nUniverse!\n  -foo\n"

# vs:
<<-TEXT
  Hello
  Universe!
    -foo
TEXT
# => "  Hello\n  Universe!\n    -foo\n"

Note that this was introduced with Ruby 2.3. On older Rubies you may use String#strip_heredoc from ActiveSupport.

<< vs <<- (or <<~)

You may also omit the dash or tilde and just write <<EOT. If you do this, your terminating sequence must be at the very beginning of the line. It's less pretty and there is rarely a reason to use it:

def foo
  puts(<<TEXT)
      Hello!
TEXT
end

Multiple heredocs in one line

If you have more than one multi-line string that you want to use in one line, you can just put your heredocs strings below each other. Example:

def long_messages
  html_escape(<<-ONE) + '<hr />' + html_escape(<<-TWO)
    Here goes my first very long message.
    Yeehaw!
  ONE
    This is the second message which is still long.
    It is long indeed.
  TWO
end
Arne Hartherz over 10 years ago
This website uses short-lived cookies to improve usability.
Accept or learn more