6

When writing Ruby (client scripts) I see three ways to build longer strings, including line-endings, all of which "smell" kind of ugly to me.

Are there any cleaner and nicer ways?

The variable-incrementing.

if render_quote?
  quote =  "Now that there is the Tec-9, a crappy spray gun from South Miami."
  quote += "This gun is advertised as the most popular gun in American crime. Do you believe that shit?"
  quote += "It actually says that in the little book that comes with it: the most popular gun in American crime."
  quote += "Like they're actually proud of that shit."
  puts quote
end

Heredocs (and unclosed quotes).

if render_quote?
  quote =<<EOS
Now that there is the Tec-9, a crappy spray gun from South Miami.
This gun is advertised as the most popular gun in American crime. Do you believe that shit?
It actually says that in the little book that comes with it: the most popular gun in American crime.
Like they're actually proud of that shit.
EOS

  puts quote
end

Or, by simply not adding a closing tag:

if render_quote?
  quote = "Now that there is the Tec-9, a crappy spray gun from South Miami.
This gun is advertised as the most popular gun in American crime. Do you believe that shit?
It actually says that in the little book that comes with it: the most popular gun in American crime.
Like they're actually proud of that shit."

  puts quote
end

Or, optionally, with a gsub to fix the identation-issues (yuk!?).

Concatenating.

if render_quote?
  quote =  "Now that there is the Tec-9, a crappy spray gun from South Miami."
  quote += "This gun is advertised as the most popular gun in American crime. Do you believe that shit?"
  quote += "It actually says that in the little book that comes with it: the most popular gun in American crime."
  quote += "Like they're actually proud of that shit."
  puts quote
end

( quote from Samuel L. Ipsum )

I am aware that having such strings (i.e. view-logic) trough my scripts is a smell in itself, but don't know of a pattern (other then po-files or so) to clean this up.

Community
  • 1
  • 1
berkes
  • 26,996
  • 27
  • 115
  • 206
  • 1
    How's your concatenating is different from variable-incrementing? Did you list the same thing twice? – Sergio Tulentsev Nov 13 '12 at 11:14
  • @SergioTulentsev it is a made-up name by me :). Because foo++ and foo+= is "incremental" updating the var. You do kindof the same here. – berkes Nov 13 '12 at 12:35

3 Answers3

5

Note that adjacent string literals are concatenated. You can combine this with line-continuing character \.

if render_quote?
  quote =
  "Now that there is the Tec-9, a crappy spray gun from South Miami. " \
  "This gun is advertised as the most popular gun in American crime. " \
  "Do you believe that shit?" \
  "It actually says that in the little book that comes with it: " \
  "the most popular gun in American crime. " \
  "Like they're actually proud of that shit."
  puts quote
end
sawa
  • 165,429
  • 45
  • 277
  • 381
  • Not sure why you simply wouldn't remove the quotes until the very last one and simply escape the return. You have spaces and quotes on each line that you simply don't need. – vgoff Nov 13 '12 at 14:47
  • @vgoff I don't know what you mean by "escape the return". I added spaces after the non-last lines so that The next line does not get concatenated right after the punctuation mark. – sawa Nov 13 '12 at 14:57
  • That backslash is an escape, the character after that is a return. So it escapes the return. Had you simply not placed the quote, left the last character in the string and had the backslash-enter, then the enter ends up being "escaped" and not seen as part of the line. Does that explain what I am saying? So with the escaped newline, to Ruby it looks like a bunch of strings concurrently placed, with one space between the strings. – vgoff Nov 13 '12 at 15:44
  • @vgoff I see what you mean. I didn't realize that part. But then, you would not be able to indent the lines without having unwanted spaces. – sawa Nov 13 '12 at 15:53
  • Sure, you would. You are only escaping the returns... if that is what you want. If that is not what you want, and you want to keep the returns, then keep them. The reason you are using them here is mostly to tell Ruby that you are not done with the assignment yet. So it doesn't have much to do with the indenting. This was also why I was kind of surprised that the answer was accept if the 'clean' stipulation was a measurement. You are basically fighting with Ruby at this point. – vgoff Nov 13 '12 at 16:00
  • @vgoff Be surprised as much as you want. I don't care. – sawa Nov 13 '12 at 16:32
  • Funny. Wasn't meant mean, or bad. Just was surprised. I like surprises. It means that I learned something. – vgoff Nov 13 '12 at 16:58
2

Your code wasn't working for me with the dash afterwards... but this works, doesn't require additional escaping of new lines, and simply says what it is doing on the HereDoc.

if render_quote?
  quote = <<-EOS.strip.split.join(' ')
    Now that there is the Tec-9, a crappy spray gun from South Miami.
    This gun is advertised as the most popular gun in American crime. Do you believe that shit?
    It actually says that in the little book that comes with it: the most popular gun in American crime.
    Like they're actually proud of that shit.
  EOS

  puts quote
end

The dash before the EOS signifies that I will be able to use the EOS in an indented manner.

vgoff
  • 10,980
  • 3
  • 38
  • 56
  • 1
    If you don't use the strip, it will ensure that the indenting is there if you want it. No additional spaces on the right hand side. Thanks Sawa for mentioning that. – vgoff Nov 13 '12 at 17:04
2

Since Ruby 2.3 you have the squiggly heredoc to avoid indentations in the string and still keep indentations in your code.

See here for more info.

Here the example from that page.

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

If you don't mind the indentations you can also use the %Q{} syntax like this, the %Q gives string substitution, the %q not.

warning_message = %Q{
  Subscription expiring soon!
  Your free trial will expire in #{days_until_expiration} days.
  Please update your billing information.
}
peter
  • 41,770
  • 5
  • 64
  • 108