Ruby-way (TM) desde Ruby 2.3: use el HEREDOC ondulado <<~
para definir una cadena de varias líneas con líneas nuevas y sangría adecuada:
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..."
Si la sangría adecuada no es una preocupación, las comillas simples y dobles pueden abarcar varias líneas en 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..."
Si las comillas simples o dobles son engorrosas porque eso requeriría mucho escape, entonces la notación literal de cadena de porcentaje %
es la solución más flexible:
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..."
Si el objetivo es evitar las nuevas líneas (que causan tanto el HEREDOC ondulado, las comillas como el literal de cadena de porcentaje), entonces se puede usar una continuación de línea colocando una barra diagonal inversa \
como el último carácter no en blanco en una línea. Esto continuará la línea y hará que Ruby concatene las cadenas de forma consecutiva (tenga cuidado con esos espacios dentro de la cadena citada):
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..."
Si usa Rails String.squish
, eliminará la cadena de espacios iniciales y finales y colapsará todos los espacios en blanco consecutivos (líneas nuevas, pestañas y todo) en un solo espacio:
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..."
Más detalles:
Sintaxis de Ruby HEREDOC
La notación de documento aquí para cadenas funciona es una forma de designar bloques largos de texto en línea en el código. Se inicia <<
seguido de una Cadena definida por el usuario (el finalizador de Fin de Cadena). Todas las siguientes líneas se concatenan hasta que se encuentra el finalizador de Fin de cadena al comienzo de una línea:
puts <<HEREDOC
Text Text Text Text
Bla Bla
HEREDOC
# -> "Text Text Text Text\nBlaBla"
El terminador End of String se puede elegir libremente, pero es común usar algo como "EOS" (End of String) o algo que coincida con el dominio de la cadena como "SQL".
HEREDOC admite la interpolación de manera predeterminada o cuando el terminador EOS se cita dos veces:
price = 10
print <<"EOS" # comments can be put here
1.) The price is #{price}.
EOS
# -> "1.) The price is 10."
La interpolación se puede deshabilitar si el terminador EOS se cita solo:
print <<'EOS' # Disabled interpolation
3.) The price is #{price}.
EOS
# -> "3.) The price is #{price}."
Una restricción importante de la <<HEREDOC
es que el terminador de Fin de cadena debe estar al principio de la línea:
puts <<EOS
def foo
print "foo"
end
EOS
EOS
#-> "....def foo\n......print "foo"\n....end\n..EOS
Para evitar esto, <<-
se creó la sintaxis. Permite sangrar el terminador EOS para que el código se vea mejor. Las líneas entre el <<-
terminador y el EOS todavía se usan en toda su extensión, incluida toda sangría:
puts <<-EOS # Use <<- to indent End of String terminator
def foo
print "foo"
end
EOS
# -> "..def foo\n....print "foo"\n..end"
Desde Ruby 2.3, ahora tenemos el HEREDOC ondulado que <<~
elimina los espacios en blanco iniciales :
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"
<< ~ ignora las líneas vacías y las líneas que solo contienen pestañas y espacios.
puts <<~EOS.inspect
Hello
World!
EOS
#-> "Hello\n..World!"
Si se usan tabulaciones y espacios, las pestañas se consideran iguales a 8 espacios. Si la línea con menos sangría está en el medio de una pestaña, esta pestaña no se elimina.
puts <<~EOS.inspect
<tab>One Tab
<space><space>Two Spaces
EOS
# -> "\tOne Tab\nTwoSpaces"
HEREDOC puede hacer algunas locuras, como ejecutar comandos usando backticks:
puts <<`EOC`
echo #{price}
echo #{price * 2}
EOC
Las definiciones de cadenas HEREDOC se pueden "apilar", lo que significa que el primer terminador EOS (EOSFOO a continuación) finalizará la primera cadena e iniciará la segunda (EOSBAR a continuación):
print <<EOSFOO, <<EOSBAR # you can stack them
I said foo.
EOSFOO
I said bar.
EOSBAR
No creo que nadie lo use como tal, pero en <<EOS
realidad es solo una cadena literal y se puede poner donde sea que se pueda poner una cadena:
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
Si no tiene Ruby 2.3, pero Rails >=
3.0, puede usar el String.strip_heredoc
que hace lo mismo que<<~
# 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
Porcentaje de cadenas literales
Ver RubyDoc para saber cómo utilizar el signo de porcentaje seguido de una cadena en un par de paréntesis, tales como %(...)
, %[...]
,%{...}
, etc., o un par de cualquier carácter no alfanumérico, como%+...+
Ultimas palabras
Por último, para obtener la respuesta a la pregunta original "¿Hay alguna forma de implicar concatenación?" respondió: Ruby siempre implica concatenación si se encuentran dos cadenas (comillas simples y dobles) consecutivas:
puts "select..." 'from table...' "where..."
# -> "select...from table...where..."
La advertencia es que esto no funciona a través de saltos de línea, porque Ruby está interpretando el final de la declaración y la línea consecuente de solo cadenas en una línea no hace nada.