Heredocs and how to use them in Ruby and Rails

4 minute read

What is heredoc?

Heredoc allows us to specify a string as a block of texts where new lines and indentations are maintained.

This is useful in Ruby for various cases like specifying multiline text strings, multiline method dynamic definitions and more.

There are many ways to use Heredoc in Ruby and in Rails, with different utilities. This can be confusing at times where to use which version. Let’s do a run-down of different ways to use it.

How to define?

We can define multiline strings in Ruby in the following ways:

> str = <<HEREDOC > This is > a sample > text. >HEREDOC => " This is

a sample

text.

"

> str = <<-HEREDOC > This is > a sample > text. > HEREDOC => " This is

a sample

text.

"

Here HEREDOC is the start and end marker. It can be any string.

This can be used in embedding the code snippets like SQL statements or HTML. For Example:

> query = <<-SQL > Select * from users > where name = 'John' > SQL => "Select * from users

where name = 'John'

"

There is a very subtle difference between << and <<- . << expects end marker( HEREDOC in our case) should be at the start of the line. Whitespace before the marker at the end of the line is invalid syntax.

We can use <<- instead if we need to add more spaces for better reading of the text.

> str = <<-HEREDOC > Notice the spaces immediately before > the end. > HEREDOC => "Notice the space immediately before

the end.

"

Input Redirection

<< can be used for input redirection in Ruby. Below is an example of heredoc with input redirection.

> File.open('test.rb', 'w') do |f| > f << <<-HEREDOC > This is a test > File > HEREDOC end

Now let’s read the content of the test.rb file.

> f = File.open('test.rb', 'r') > f.read => " This is a test

File

"

We can also use %Q instead of heredoc . The following example will add a new line at the start and end of the string.

>str = %Q( > This is > a sample > text. >) => "

This is

a sample

text.

"

Interpolation

Strings inside heredoc are treated as double-quoted strings, hence string interpolation is possible with heredoc.

> name = 'John' > str = <<-HEREDOC My Name is #{name}. HEREDOC => " My Name is

John.

"

> name = 'John' > str = <<-"HEREDOC" My Name is #{name}. HEREDOC => " My Name is

John.

"

We can opt-out the interpolation by using single-quoted heredoc start marker string. For example:

> name = 'John' > str = <<-'HEREDOC' My Name is #{name}. HEREDOC => " My Name is

#{name}.

"

How to remove unwanted spaces?

We can remove unwanted spaces using gsub .

> str = <<-HEREDOC.gsub(/^\s+/, "") This is a sample text. HEREDOC => "This is a

sample text.

"

In Rails, there is a method strip_heredoc which we can use to remove the unwanted spaces.

> str = <<-HEREDOC.strip_heredoc This is a sample text. HEREDOC => "This is a

sample text.

"

Squiggly heredoc

Ruby 2.3 introduced the squiggly heredoc <<~ to remove the spaces due to indentation.

> str = <<~HEREDOC This is a sample text. HEREDOC => "This is a

sample text.

"

Let’s take a look at another example:

> str = <<~HEREDOC Hello,

Good Morning My name is John. HEREDOC => "Hello,

Good Morning

My name is John.

" > puts str => Hello, => Good Morning => My name is John.

Now, we will use strip_heredoc instead of <<~ .

> str = <<-HEREDOC.strip_heredoc Hello,

Good Morning My name is John. HEREDOC => " Hello,

Good Morning

My name is John.

" > puts str => Hello, => Good Morning => My name is John.

As we can see that strip_heredoc didn’t remove the leading spaces in the above example because the strip_heredoc documentation says

It looks for the least indented non-empty line in the whole string and removes that amount of leading whitespace.

This is the only difference between strip_heredoc and <<~ .

Convert multiline into one line

In Rails, we can use String#squish to convert multiline into one line.

> str = <<~HEREDOC.squish This is a sample text. HEREDOC => "This is a sample text."

Shell Command

To execute shell commands, we can use backticks.

> str = <<~`HEREDOC` date HEREDOC => "Wed Mar 25 18:51:08 IST 2020

"

Summary

We looked at the different ways of defining multiline string in Ruby and Rails using heredoc .

Hopefully, it will be less confusing next time we need to make use of one of the heredoc versions.