Have you ever had to write a nicely indented multiline string in Ruby? If you have, you already know that Ruby doesn’t have a nice out-of-the-box solution for this problem. At least it hadn’t until a week ago when the squiggly heredoc was introduced…
To be honest, I actually rarely need to use multiline strings, but when I do, it really gets on my nerves that Ruby lacks an upfront way to do them. Every time I need to write a multiline string, I google it and hope that someone has found a way to write it without performing ugly ‘hacks’ that can be found in this Stack Overflow post.
The first thing that comes to mind when doing multiline strings is using the HEREDOC
syntax.
class Subscription
def warning_message
<<-HEREDOC
Subscription expiring soon!
Your free trial will expire in #{days_until_expiration} days.
Please update your billing information.
HEREDOC
end
end
Unfortunately, the string inside the heredoc is going to be output with 6 leading spaces, and so far that’s never been the expected behavior for me:
text
Subscription expiring soon!
Your free trial will expire in 5 days.
Please update your billing information.
One solution for this would be to indent the string to the left margin, but that leaves our code looking really ugly and badly indented:
class Subscription
def warning_message
<<-HEREDOC
Subscription expiring soon!
Your free trial will expire in #{days_until_expiration} days.
Please update your billing information.
HEREDOC
end
end
Other ways like removing multiple leading whitespace characters with #gsub
, appending multiple strings to each other and so on can be found in the above mentioned Stack Overflow post. There isn’t a nice way to do this in pure Ruby, however Rails does have a ’patch’ to support this behavior with the #strip_heredoc method, but it’s one method call too much to support a simple behavior like this.
Meet the squiggly heredoc
Besides numerous new features in Ruby 2.3, such as the safe navigation operator or Hash#dig
(read more about new features in Ruby 2.3 in this post), there will be a new and improved HEREDOC syntax called the squiggly HEREDOC that does what I’ve always expected the regular HEREDOC syntax to do – it strips the leading whitespace (similar to the #strip_heredoc
method in Rails)
It looks quite similar to HEREDOC, except instead of writing <<-HEREDOC
, you will substitute the hyphen with a tilda: <<~HEREDOC
.
We can finally write our multiline strings in a nice manner with a minimal change (squint hard, you can barely notice it):
class Subscription
def warning_message
<<~HEREDOC
Subscription expiring soon!
Your free trial will expire in #{days_until_expiration} days.
Please update your billing information.
HEREDOC
end
end
The rule for stripping enough whitespace:
The indentation of the least-indented line will be
removed from each line of the content.
This feature was suggested by Sikachu 2 years ago, merged to Ruby on December 7th, and you can read more about it in this pull request by Ben Miller and this commit by Nobu, the mysterious No. 1 committer to the Ruby core.
You can check out all the new features in Ruby 2.3 by installing ruby 2.3.0preview2
, or simply wait until Christmas when the new official minor version will be released.