Question

Ruby Multi-Line Strings Without Concatenation

rubycode-formatting

Question

In Ruby, is there a cleaner way to write a long string across multiple lines without manually concatenating each part with +?

For example, instead of writing:

conn.exec 'select attr1, attr2, attr3, attr4, attr5, attr6, attr7 ' +
          'from table1, table2, table3, etc, etc, etc, etc, etc, ' +
          'where etc etc etc etc etc etc etc etc etc etc etc etc etc'

is there a way to split the string over multiple lines while still treating it as one string automatically?

I am especially looking for a more readable way to format long SQL statements.

Short Answer

By the end of this page, you will understand how Ruby handles multi-line strings and how to write long text more cleanly without using repeated + concatenation. You will see practical options such as heredocs, backslash line continuation, and adjacent string literals, with a focus on readable SQL queries.

Concept

Ruby gives you several ways to represent long strings across multiple lines. This matters because long strings appear often in real programs: SQL queries, HTML templates, error messages, JSON payloads, and command-line output.

The core idea is that you do not always need to build a long string with +. In many cases, Ruby lets you write text in a more readable form.

The most useful approaches are:

  • Heredoc: best for long multi-line text such as SQL or templates
  • Adjacent string literals: Ruby can combine neighboring string literals automatically in some contexts
  • Backslash line continuation: keeps the string logically on one line in Ruby code

For SQL specifically, heredoc is usually the clearest choice because it preserves formatting and makes the query easier to read and maintain.

A key thing to remember is that multi-line source code and multi-line string content are not always the same:

  • Sometimes you want the Ruby code on multiple lines, but the final string should be one line
  • Sometimes you want the final string itself to contain line breaks

Choosing the right approach depends on which of those you want.

Mental Model

Think of a string like a note you want to write on paper.

  • Using + is like cutting the note into pieces and taping them together.
  • Using a heredoc is like writing the whole note naturally in one block.
  • Using adjacent literals is like putting several note fragments next to each other and letting Ruby combine them.

If the content is naturally long, like an SQL query, heredoc is usually the most natural way to write it.

Take Quiz

Syntax and Examples

1. Heredoc

A heredoc lets you write a string block over multiple lines.

sql = <<~SQL
  SELECT attr1, attr2, attr3, attr4, attr5, attr6, attr7
  FROM table1, table2, table3
  WHERE table1.id = table2.table1_id
SQL

conn.exec(sql)

Why this is useful

  • Very readable
  • Great for SQL, HTML, JSON, and long messages
  • Keeps the formatting close to how the final text should look

<<~SQL also removes common indentation, so your code can stay neatly indented.

2. Adjacent string literals

Ruby can join string literals written next to each other.

sql = 'SELECT attr1, attr2, attr3 ' 
      'FROM table1, table2, table3 ' 
      'WHERE table1.id = table2.table1_id'

conn.exec(sql)

This is much cleaner than using + repeatedly.

3. Backslash line continuation

If you want one logical string split across lines in code, you can continue the expression with \.

sql = 'SELECT attr1, attr2, attr3 ' \
      'FROM table1, table2, table3 ' \
      'WHERE table1.id = table2.table1_id'

This still relies on separate string literals, but the line continuation makes the code valid across lines.

4. Multi-line string with embedded newlines

If you use a heredoc, the string includes line breaks.

sql = <<~SQL
  SELECT name
  FROM users
  WHERE active = true
SQL

That means the final string contains \n characters. Most SQL libraries handle this fine.

Recommended style for SQL

conn.exec(<<~SQL)
  SELECT attr1, attr2, attr3, attr4, attr5, attr6, attr7
  FROM table1, table2, table3
  WHERE table1.id = table2.table1_id
SQL

This is usually the most readable option.

Step by Step Execution

Consider this example:

sql = 'SELECT name, email ' 
      'FROM users ' 
      'WHERE active = true'

puts sql

Step by step

  1. Ruby reads the first string literal:

    'SELECT name, email '
    
  2. Ruby sees another string literal immediately after it:

    'FROM users '
    
  3. Ruby combines them into one string.

  4. Ruby reads the third string literal:

    'WHERE active = true'
    
  5. Ruby combines that too.

  6. The final value of sql becomes:

    SELECT name, email FROM users WHERE active = true
    
  7. puts sql prints the full combined string.

Heredoc trace

Now compare that with a heredoc:

sql = <<~SQL
  SELECT name, email
  FROM users
  WHERE active = true
SQL

Ruby collects everything between <<~SQL and the closing SQL marker into one string.

The final string contains line breaks, so its value is closer to:

SELECT name, email
FROM users
WHERE active = true

This is often better for readability, especially in SQL.

Real World Use Cases

Multi-line strings are common in real Ruby programs.

SQL queries

query = <<~SQL
  SELECT id, name, email
  FROM users
  WHERE active = true
  ORDER BY name
SQL

Used in:

  • database scripts
  • reporting tools
  • background jobs
  • Rails apps with raw SQL

HTML or email templates

html = <<~HTML
  <h1>Welcome</h1>
  <p>Your account is ready.</p>
HTML

Used in:

  • email generation
  • simple server responses
  • templated notifications

JSON payloads

payload = <<~JSON
  {
    "event": "signup",
    "status": "success"
  }
JSON

Used in:

  • API testing
  • fixtures
  • mock requests

Shell commands

command = <<~CMD
  echo "Starting"
  echo "Done"
CMD

Used in:

  • automation scripts
  • deployment helpers
  • build tools
Take Quiz

Real Codebase Usage

In real projects, developers usually choose the style that makes intent most obvious.

Common patterns

1. Heredoc for long SQL

sql = <<~SQL
  SELECT users.id, users.name
  FROM users
  WHERE users.active = true
SQL

This is common because SQL is easier to review when formatted like SQL.

2. Assign once, pass later

sql = <<~SQL
  SELECT *
  FROM orders
  WHERE status = 'pending'
SQL

result = conn.exec(sql)

This helps with:

  • debugging
  • logging
  • testing
  • reusing the query

3. Inline heredoc for one-off calls

conn.exec(<<~SQL)
  SELECT *
  FROM products
  WHERE in_stock = true
SQL

Good for short one-use queries.

4. Interpolation with care

table_name = 'users'
sql = <<~SQL
  SELECT *
  FROM #{table_name}
SQL

Useful, but developers should be careful with untrusted input. For values, parameterized queries are safer than building SQL manually.

5. Guarding readability

If a string becomes too long or complex, developers usually:

  • move it into a variable
  • use heredoc
  • break the problem into smaller parts
  • avoid dense one-line SQL

Common Mistakes

1. Using + everywhere

This works, but it is noisy and harder to maintain.

sql = 'SELECT * ' +
      'FROM users ' +
      'WHERE active = true'

Prefer:

sql = 'SELECT * ' 
      'FROM users ' 
      'WHERE active = true'

or a heredoc.

2. Forgetting spaces between string parts

Broken example:

sql = 'SELECT *'
      'FROM users'

This becomes:

SELECT *FROM users

Fix it by adding spaces where needed:

sql = 'SELECT * ' 
      'FROM users'

3. Confusing code newlines with string newlines

With adjacent literals:

sql = 'SELECT * ' 
      'FROM users'

The final string is:

SELECT * FROM users

With heredoc:

sql = <<~SQL
  SELECT *
  FROM users
SQL

The final string includes actual newline characters.

4. Using single quotes when interpolation is needed

Broken example:

table = 'users'
sql = 'SELECT * FROM #{table}'

This does not interpolate.

Fix it with double quotes or interpolated heredoc:

table = 'users'
sql = "SELECT * FROM #{table}"

or:

table = 'users'
sql = <<~SQL
  SELECT * FROM #{table}
SQL

5. Building unsafe SQL strings

Broken approach:

name = params[:name]
sql = "SELECT * FROM users WHERE name = '#{name}'"

This can be unsafe if input is untrusted.

Prefer parameterized queries when inserting values into SQL.

6. Misplacing the heredoc terminator

Broken example:

sql = <<~SQL
  SELECT * FROM users
  SQL

The closing identifier must be aligned correctly for Ruby to recognize it.

Comparisons

ApproachBest forKeeps line breaks in final string?ReadabilityNotes
+ concatenationSimple dynamic joiningNo, unless added manuallyLowVerbose for long strings
Adjacent string literalsSplitting one string over code linesNoGoodClean when you just want one long string
HeredocSQL, HTML, templates, long textYesExcellentUsually the best option for formatted text
Backslash continuationContinuing an expression across linesNoFairLess expressive than heredoc

Adjacent literals vs heredoc

# Adjacent literals
sql = 'SELECT id, name ' 
      'FROM users ' 
      'WHERE active = true'

Final string:

SELECT id, name FROM users WHERE active = true
# Heredoc
sql = <<~SQL
  SELECT id, name
  FROM users
  WHERE active = true
SQL

Final string:

SELECT id, name
FROM users
WHERE active = true

Use adjacent literals when you want one flat string. Use heredoc when you want readable multi-line content.

Take Quiz

Cheat Sheet

Quick reference

Adjacent string literals

text = 'Hello, ' 
       'world'
  • Ruby combines them into one string
  • Good for long one-line output
  • Remember spaces between parts if needed

Heredoc

text = <<~TEXT
  Hello
  world
TEXT
  • Best for multi-line content
  • Preserves line breaks
  • <<~ removes common indentation

Backslash continuation

text = 'Hello, ' \
       'world'
  • Continues an expression onto the next line
  • Less readable than heredoc for large blocks

Interpolation rules

name = 'Ada'
text = "Hello, #{name}"
  • Single quotes: no interpolation
  • Double quotes: interpolation works
  • Heredoc usually supports interpolation unless using a non-interpolating form

Good SQL style

sql = <<~SQL
  SELECT id, name
  FROM users
  WHERE active = true
SQL

Watch out for

  • missing spaces between adjacent string pieces
  • accidental newlines in heredocs
  • unsafe SQL built from user input

FAQ

Can Ruby automatically concatenate strings on separate lines?

Yes. Adjacent string literals can be combined without +, as long as they are written as neighboring literals in a valid expression.

What is the cleanest way to write long SQL in Ruby?

Usually a heredoc, because it keeps the SQL readable and formatted like normal SQL.

Does a heredoc include newline characters?

Yes. A heredoc preserves line breaks inside the string.

If I do not want newline characters, should I still use a heredoc?

Usually no. If you want one flat string, adjacent string literals are often simpler.

Is + wrong for joining strings in Ruby?

No, but it is often less readable for long static strings.

Can I interpolate variables inside a multi-line Ruby string?

Yes, if you use double-quoted strings or an interpolating heredoc.

Are multi-line SQL strings safe?

The formatting style is safe, but interpolating untrusted values directly into SQL is not. Use parameterized queries for values.

What does <<~ mean in a heredoc?

It creates a heredoc and strips common indentation, which helps keep your Ruby code nicely indented.

Take Quiz

Mini Project

Description

Create a small Ruby script that builds and prints readable SQL queries using both adjacent string literals and a heredoc. This project helps you see the difference between writing one flat string and writing a formatted multi-line string.

Goal

Write a Ruby script that creates two SQL queries without using + concatenation and shows how each one is output.

Requirements

  • Create one query using adjacent string literals
  • Create one query using a heredoc
  • Print both queries to the console
  • Make the SQL readable and valid as plain text
Take Quiz

Keep learning

Related questions

View more