ruby: workarounds for nested string interpolation

1.4k Views Asked by At

In the string
"#{x ? (x.to_s + ' is ') : ''}ok", Rubocop's Style/StringConcatenation suggests avoiding the +.
But that requires a nested string interpolation
"#{x ? '#{x.to_s} is ' : ''}ok)",
which at least in Ruby 2.7 is not expanded: #{x.to_s} is treated like any other literal.

Is the + version alright because it's on the fringes of what a style guide could cover, or must one introduce a temporary variable?

tmp = x ? '#{x.to_s}  is '  : ''
"#{tmp}ok"

Context: the string is sent to a logfile. ok is actually a long list of details. x is worth logging, but only when it exists.

2

There are 2 best solutions below

1
On BEST ANSWER

Yes, a variable will make this more readable (imo):

prefix = "#{x} is " if x
"#{prefix}ok"

(this relies on the fact that nil#to_s == '')

0
On

Given that "ok" is actually:(according to the comments)

"...a long string that has even more interpolations. Duplicating that string isn't DRY".

I would go with

ok = generate_some_long_string()
ok.prepend("#{x} is ") if x
ok

This does mutate ok but based on my understanding of the question this may actually be desirable.

Nesting Interpolation

As an aside and I would not recommend it (because it is difficult to read) but nesting interpolation is completely valid ruby e.g.

x="val"
"#{x ? "#{x} is " : ""}ok"
#=> "val is ok"

This works because what is inside the interpolation closure is treated like any other ruby code. The inner double quotes open and close a new String rather than closing the first and opening another because the interpolation closure is waiting for a closing curly brace. You could technically do this at any depth.

"#{x ? "#{"the #{y = x}ue of"} #{x} is " : ""}#{y.inspect}"
#=> "the value of val is \"val\""