Diese Frage hat mich dazu gebracht, die Funktionsweise von HEREDOC zu verstehen. Verzeihen Sie mir, wenn die Antwort zu lang geworden ist.
El verschnörkelter HEREDOC <<~
ist das, wonach Sie suchen, wenn Sie eine mehrzeilige Zeichenfolge mit Zeilenumbrüchen und korrekter Einrückung (verfügbar seit Ruby 2.3):
conn.exec <<~EOS
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
EOS
# -> "select...\nfrom...\nwhere..."
Wenn eine ordnungsgemäße Einrückung nicht von Bedeutung ist, dann einfache und doppelte Anführungszeichen kann sich in Ruby über mehrere Zeilen erstrecken:
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"
# -> "select...\n from...\n where..."
Wenn einfache oder doppelte Anführungszeichen umständlich sind, weil sie eine Menge Escaping erfordern würden, dann ist die prozentuale String-Literal-Schreibweise %
ist die flexibelste Lösung:
conn.exec %(select attr1, attr2, attr3, attr4, attr5, attr6, attr7
from table1, table2, table3, etc, etc, etc, etc, etc
where (ProductLine = 'R' OR ProductLine = "S") AND Country = "...")
# -> "select...\n from...\n where..."
Wenn das Ziel ist, die Zeilenumbrüche zu vermeiden (die sowohl der verschnörkelte HEREDOC, die Anführungszeichen als auch das prozentuale Zeichenfolgenliteral verursachen), dann ist ein Zeilenfortsetzung kann durch einen Backslash verwendet werden \
als letztes Zeichen ohne Leerzeichen in einer Zeile. Dies setzt die Zeile fort und veranlasst Ruby, die Strings Rücken an Rücken zu verketten (achten Sie auf die Leerzeichen innerhalb des zitierten Strings):
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'
# -> "select...from...where..."
Wenn Sie Rails verwenden, dann String.squish
entfernt in der Zeichenkette führende und nachfolgende Leerzeichen und fasst alle aufeinander folgenden Leerzeichen (Zeilenumbrüche, Tabulatoren und alle) zu einem einzigen Leerzeichen zusammen:
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".squish
# -> "select...attr7 from...etc, where..."
Weitere Einzelheiten:
Ruby HEREDOC-Syntax
El Hier Dokumentennotation für Zeichenketten ist eine Möglichkeit, lange Textblöcke inline im Code zu kennzeichnen. Er wird gestartet durch <<
gefolgt von einer benutzerdefinierten Zeichenkette (dem End of String Terminator). Alle folgenden Zeilen werden aneinandergereiht, bis der End of String-Terminator an der allererster Schritt einer Linie:
puts <<HEREDOC
Text Text Text Text
Bla Bla
HEREDOC
# -> "Text Text Text Text\nBlaBla"
Das Ende der Zeichenkette kann frei gewählt werden, aber es ist üblich, etwas wie "EOS" (Ende der Zeichenkette) oder etwas, das dem Bereich der Zeichenkette entspricht, wie "SQL", zu verwenden.
HEREDOC unterstützt Interpolation standardmäßig oder wenn der EOS-Terminator in Anführungszeichen steht:
price = 10
print <<"EOS" # comments can be put here
1.) The price is #{price}.
EOS
# -> "1.) The price is 10."
Die Interpolation kann deaktiviert werden, wenn der EOS-Terminator in einfachen Anführungszeichen steht:
print <<'EOS' # Disabled interpolation
3.) The price is #{price}.
EOS
# -> "3.) The price is #{price}."
Eine wichtige Einschränkung der <<HEREDOC
ist, dass das Ende der Zeichenkette am Anfang der Zeile stehen muss:
puts <<EOS
def foo
print "foo"
end
EOS
EOS
#-> "....def foo\n......print "foo"\n....end\n..EOS"
Um dies zu umgehen, wird die <<-
Syntax erstellt wurde. Sie erlaubt es, den EOS-Terminator einzurücken, um den Code schöner aussehen zu lassen. Die Zeilen zwischen den <<-
und EOS-Terminator werden weiterhin in vollem Umfang einschließlich aller Einrückungen verwendet:
def printExample
puts <<-EOS # Use <<- to indent End of String terminator
def foo
print "foo"
end
EOS
end
# -> "....def foo\n......print "foo"\n....end"
Seit Ruby 2.3 haben wir nun das verschnörkelte HEREDOC <<~
wodurch führende Leerzeichen entfernt werden:
puts <<~EOS # Use the squiggly HEREDOC <<~ to remove leading whitespace (since Ruby 2.3!)
def foo
print "foo"
end
EOS
# -> "def foo\n..print "foo"\nend"
Leere Zeilen und Zeilen, die nur Tabulatoren und Leerzeichen enthalten, werden von <<~ ignoriert.
puts <<~EOS.inspect
Hello
World!
EOS
#-> "Hello\n..World!"
Werden sowohl Tabulatoren als auch Leerzeichen verwendet, gelten Tabulatoren als gleichwertig mit 8 Leerzeichen. Befindet sich die Zeile mit der geringsten Einrückung in der Mitte eines Tabulators, wird dieser nicht entfernt.
puts <<~EOS.inspect
<tab>One Tab
<space><space>Two Spaces
EOS
# -> "\tOne Tab\nTwoSpaces"
HEREDOC kann einige verrückte Dinge tun, zum Beispiel Befehle mit Backticks ausführen:
puts <<`EOC`
echo #{price}
echo #{price * 2}
EOC
HEREDOC-String-Definitionen können "gestapelt" werden, was bedeutet, dass der erste EOS-Terminator (EOSFOO unten) den ersten String beendet und den zweiten beginnt (EOSBAR unten):
print <<EOSFOO, <<EOSBAR # you can stack them
I said foo.
EOSFOO
I said bar.
EOSBAR
Ich glaube nicht, dass jemand es jemals als solches benutzen würde, aber die <<EOS
ist eigentlich nur ein String-Literal und kann überall dort eingefügt werden, wo normalerweise ein String eingefügt werden kann:
def func(a,b,c)
puts a
puts b
puts c
end
func(<<THIS, 23, <<THAT)
Here's a line
or two.
THIS
and here's another.
THAT
Wenn Sie nicht Ruby 2.3 haben, sondern Rails >=
3.0 dann können Sie String.strip_heredoc
was dasselbe bewirkt wie <<~
# File activesupport/lib/active_support/core_ext/string/strip.rb, line 22
class String
def strip_heredoc
gsub(/^#{scan(/^[ \t]*(?=\S)/).min}/, "".freeze)
end
end
puts <<-USAGE.strip_heredoc # If no Ruby 2.3, but Rails >= 3.0
This command does such and such.
Supported options are:
-h This message
...
USAGE
Fehlersuche
Wenn Sie Fehler sehen, wenn Ruby Ihre Datei parst, dann ist es sehr wahrscheinlich, dass Sie entweder zusätzliche führende oder nachgestellte Leerzeichen mit einem HEREDOC oder zusätzliche nachgestellte Leerzeichen mit einem verschnörkelten HEREDOC haben. Zum Beispiel:
Was Sie sehen:
database_yml = <<~EOS
production:
database: #{fetch(:user)}
adapter: postgresql
pool: 5
timeout: 5000
EOS
Was Ruby Ihnen erzählt:
SyntaxError: .../sample.rb:xx: can't find string "EOS" anywhere before EOF
...sample.rb:xx: syntax error, unexpected end-of-input, expecting `end'
Was ist der Fehler?
Beachten Sie die zusätzlichen Leerzeichen nach dem abschließenden EOS.
Prozentuale String-Literale
Ver RubyDoc für die Verwendung des Prozentzeichens gefolgt von einer Zeichenkette in einem Klammerpaar wie z. B. einer %(...)
, %[...]
, %{...}
, usw. oder ein Paar beliebiger nicht-alphanumerischer Zeichen wie %+...+
Letzte Worte
Zuletzt, um die Antwort auf die ursprüngliche Frage "Gibt es eine Möglichkeit, die Verkettung zu implizieren?" beantwortet: Ruby impliziert immer eine Verkettung, wenn zwei Zeichenketten (einfach und doppelt zitiert) hintereinander gefunden werden:
puts "select..." 'from table...' "where..."
# -> "select...from table...where..."
Die Einschränkung ist, dass dies nicht über Zeilenumbrüche hinweg funktioniert, da Ruby ein Ende der Anweisung interpretiert und die Folgezeile von Strings allein in einer Zeile nichts bewirkt.