Ruby-way (TM) od Ruby 2.3: Aby zdefiniować wieloliniowy ciąg znaków z nowymi liniami i prawidłową identyfikacją, użyj zawijasowego HEREDOC <<~
:
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..."
Jeśli poprawna identyfikacja nie stanowi problemu, wówczas pojedyncze i podwójne cudzysłowy mogą obejmować wiele wierszy w języku Ruby:
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..."
Jeśli pojedyncze lub podwójne cudzysłowy są kłopotliwe, ponieważ wymagałoby to mnożenia znaków ucieczki, to oznaczenie literału procentowego ciągu %
jest najbardziej elastycznym rozwiązaniem:
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..."
Jeśli celem jest uniknięcie nowych linii (które spowodują zarówno zawijany HEREDOC, cudzysłowy, jak i procent literału łańcucha), to odwrotny ukośnik, jako ostatni znak niebiałej spacji, będzie kontynuował linię i spowoduje, że Ruby połączy łańcuchy z powrotem do tyłu (uważaj na spacje w cytowanym ciągu):
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..."
Jeśli używasz Railsów, String.squish
usunie ciąg początkowej i końcowej spacji i zwinie wszystkie kolejne białe spacje (znaki nowej linii, tabulatory i wszystkie) w jedną spację:
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...from...where..."
Więcej szczegółów:
Ruby Składnia HEREDOC
Działa tutaj notacja dokumentacyjna dla ciągów znaków, która jest sposobem na oznaczenie długich bloków tekstu w kodzie. Po nim <<
następuje zdefiniowany przez użytkownika ciąg znaków (terminator końca łańcucha). Wszystkie następujące wiersze są konkatenowane do momentu znalezienia terminatora End of String na samym początku wiersza:
puts <<HEREDOC
Text Text Text Text
Bla Bla
HEREDOC
# -> "Text Text Text Text\nBlaBla"
Terminator końca łańcucha można wybierać dowolnie, ale często używa się czegoś takiego jak „EOS” (koniec łańcucha) lub czegoś, co pasuje do domeny łańcucha, np. „SQL”.
HEREDOC domyślnie obsługuje interpolację lub gdy podwójny cudzysłów terminatora EOS:
price = 10
print <<"EOS" # comments can be put here
1.) The price is #{price}.
EOS
# -> "1.) The price is 10."
Interpolację można wyłączyć, jeśli terminator EOS jest cytowany:
print <<'EOS' # Disabled interpolation
3.) The price is #{price}.
EOS
# -> "3.) The price is #{price}."
Jednym ważnym ograniczeniem <<HEREDOC
jest to, że terminator końca łańcucha musi znajdować się na początku wiersza:
puts <<EOS
def foo
print "foo"
end
EOS
EOS
#-> "....def foo\n......print "foo"\n....end\n..EOS
Aby obejść ten problem, utworzono <<-
składnię. Umożliwia wcięcie terminatora EOS, dzięki czemu kod wygląda ładniej. Linie między <<-
terminatorem i terminatorem EOS są nadal używane w pełnym zakresie, włączając wszystkie wcięcia:
puts <<-EOS # Use <<- to indent End of String terminator
def foo
print "foo"
end
EOS
# -> "..def foo\n....print "foo"\n..end"
Od Ruby 2.3 mamy teraz zawijas HEREDOC <<~
usuwa wiodące białe znaki:
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"
Puste linie i linie zawierające tylko tabulatory i spacje są ignorowane przez << ~
puts <<~EOS.inspect
Hello
World!
EOS
#-> "Hello\n..World!"
Jeśli używane są zarówno tabulatory, jak i spacje, tabulatory są traktowane jako równe 8 spacjom. Jeśli linia z najmniejszymi wcięciami znajduje się na środku karty, karta ta nie jest usuwana.
puts <<~EOS.inspect
<tab>One Tab
<space><space>Two Spaces
EOS
# -> "\tOne Tab\nTwoSpaces"
HEREDOC może robić szalone rzeczy, takie jak wykonywanie poleceń za pomocą odwrotnych poleceń:
puts <<`EOC`
echo #{price}
echo #{price * 2}
EOC
Definicje ciągów HEREDOC można „ustawiać w stos”, co oznacza, że pierwszy terminator EOS (poniżej EOSFOO) zakończy pierwszy ciąg i rozpocznie drugi (poniżej EOSBAR):
print <<EOSFOO, <<EOSBAR # you can stack them
I said foo.
EOSFOO
I said bar.
EOSBAR
Nie sądzę, aby ktokolwiek kiedykolwiek używałby go jako takiego, ale <<EOS
tak naprawdę jest to dosłownie ciąg znaków i można go umieścić wszędzie tam, gdzie zwykle można go umieścić:
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
Jeśli nie masz Ruby 2.3, ale Rails >=
3.0, możesz użyć String.strip_heredoc
tego samego co<<~
# 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
Procent literałów łańcuchowych
Zobacz RubyDoc do sposobu korzystania z znak procentu po którym następuje ciąg w nawiasach powiązać takie jak %(...)
, %[...]
, %{...}
, itd. Lub parę jakiegokolwiek charakteru niealfanumeryczne takich jak%+...+
Ostatnie słowa
Wreszcie, aby uzyskać odpowiedź na pierwotne pytanie „Czy istnieje sposób sugerowania konkatenacji?” odpowiedział: Ruby zawsze oznacza konkatenację, jeśli dwa ciągi (pojedyncze i podwójne cudzysłowy) zostaną znalezione jeden po drugim:
puts "select..." 'from table...' "where..."
# -> "select...from table...where..."
Zastrzeżenie polega na tym, że nie działa to w przypadku łamania linii, ponieważ Ruby interpretuje koniec instrukcji, a wynikowa linia samych ciągów w linii nic nie robi.