How Do You Concatenate Heredoc Strings in Ruby?

If you’re working with SQL queries or other multi-line strings in Ruby, you might prefer using heredoc syntax (<<-SQL) for its readability and syntax highlighting benefits. However, concatenating heredoc strings can sometimes lead to unexpected results due to hidden newline characters. Let’s explore how to merge heredoc strings seamlessly while preserving (or removing) newlines to build the final string you need.

Understanding Heredoc Behavior in Ruby

Heredoc syntax in Ruby captures all text between the opening <<-SQL and the closing SQL delimiter, including newline characters. For example:

base_sql = <<-SQL
  select * from table
SQL

condition = <<-SQL
  where table.column = true
SQL

Here, base_sql becomes " select * from table\n" (with a trailing newline \n), and condition becomes " where table.column = true\n". When you concatenate them:

full_query = base_sql + condition

The result is:

"  select * from table\n  where table.column = true\n"

While this looks correct in Ruby, you might notice extra spaces or newlines when executing the SQL. Let’s break down how to control these characters.

Use String Concatenation as-Is

If your SQL engine tolerates newlines and indentation, simply using + to concatenate works:

full_query = base_sql + condition

This produces:

  select * from table
  where table.column = true

Pros:

  • Simple and straightforward.
  • Heredoc syntax retains editor highlighting.

Cons:

  • Adds leading spaces (from heredoc indentation).
  • Includes trailing newlines (may or may not matter for your use case).

Strip Unwanted Spaces and Newlines

If you want to remove leading spaces (from heredoc indentation) or trailing newlines, use .chomp or the squiggly heredoc (<<~):

Remove Trailing Newlines with .chomp

base_sql = <<-SQL.chomp
  select * from table
SQL

condition = <<-SQL.chomp
  where table.column = true
SQL

full_query = "#{base_sql} #{condition}"
# => "select * from table where table.column = true"

Use Squiggly Heredoc to Remove Leading Spaces

Ruby’s <<~ syntax strips leading whitespace, which is helpful for indentation:

base_sql = <<~SQL.chomp
  select * from table
SQL
# => "select * from table"

condition = <<~SQL.chomp
  where table.column = true
SQL
# => "where table.column = true"

full_query = "#{base_sql} #{condition}"

Result:

select * from table where table.column = true

Interpolate Heredocs Directly

You can combine heredocs into a single string using interpolation:

full_query = <<~SQL
  #{base_sql.strip}
  #{condition.strip}
SQL

This approach gives you full control over formatting and newlines.

Why Does the Original Example “Work” but Look Odd?

In your original code:

base_sql + condition

The output is technically correct, but Ruby’s #inspect method displays strings with \n and + to indicate concatenation. When printed or used in a query, the newlines behave as expected:

puts base_sql + condition
# Output:
#   select * from table
#   where table.column = true

The confusion arises from how Ruby represents strings internally, not the actual output.

Final Thoughts

Concatenating heredoc strings in Ruby is straightforward once you understand how newlines and indentation work. Use:

  • + for simple concatenation.
  • .chomp or <<~ to trim newlines and spaces.
  • String interpolation for dynamic formatting.

Heredocs are excellent for maintaining readability and editor features like syntax highlighting. Just remember to test the final string output to ensure it meets your requirements (especially for systems like SQL that may not care about whitespace but humans do!).

Related blog posts