Romper cadenas largas en múltiples líneas en Ruby sin eliminar nuevas líneas


Recientemente decidimos en mi trabajo una guía de estilo ruby. Uno de los edictos es que ninguna línea debe tener más de 80 caracteres. Dado que este es un proyecto de Rails, a menudo tenemos cadenas que son un poco más largas, es decir, "El usuario X quería enviarle un mensaje sobre la Cosa Y" que no siempre encaja dentro del límite de estilo de 80 caracteres.

Entiendo que hay tres maneras de tener una cadena larga que abarque varias líneas:

  • HEREDOC
  • %Q {}
  • cadena Real concatenación.

Sin embargo, todos estos casos terminan tomando más ciclos de cómputo, lo que parece tonto. Concatenación de cadenas obviamente, pero para HEREDOC y % Q tengo que eliminar las nuevas líneas, a través de algo así .gsub(/\n n/,").

¿Hay una forma de sintaxis pura para hacer esto, que es equivalente a tener la cadena completa en una línea? El objetivo es, obviamente, no gastar ningún ciclo extra solo porque quiero que mi código sea un poco más legible. (Sí, me doy cuenta de que tengo que hacer ese intercambio mucho...pero para la longitud de la cuerda, esto parece una tontería.)

Actualizar: Las barras invertidas no son exactamente lo que quiero porque pierdes sangría, lo que realmente afecta el estilo/legibilidad.

Ejemplo:

if foo
  string = "this is a \  
string that spans lines"  
end

Encuentro lo anterior un poco difícil de leer.

EDIT : He añadido una respuesta a continuación; tres años más tarde ahora tenemos el squiggly heredoc.

Author: chug2k, 2012-05-09

5 answers

Tal vez esto es lo que estás buscando?

string = "line #1"\
         "line #2"\
         "line #3"

p string # => "line #1line #2line #3"
 348
Author: Jessehz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-09 21:10:20

Puede usar \ para indicar que cualquier línea de Ruby continúa en la siguiente línea. Esto también funciona con cadenas:

string = "this is a \
string that spans lines"

puts string.inspect

Saldrá "this is a string that spans lines"

 46
Author: Emily,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-09 19:01:53

Tres años más tarde, ahora hay una solución en Ruby 2.3: El heredoc squiggly.

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

Enlace de entrada de blog: https://infinum.co/the-capsized-eight/articles/multiline-strings-ruby-2-3-0-the-squiggly-heredoc

La sangría de la línea con menos sangría será eliminado de cada línea del contenido.

 30
Author: chug2k,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-03 08:57:09

Tuve este problema cuando intento escribir una url muy larga, lo siguiente funciona.

image_url = %w(
    http://minio.127.0.0.1.xip.io:9000/
    bucket29/docs/b7cfab0e-0119-452c-b262-1b78e3fccf38/
    28ed3774-b234-4de2-9a11-7d657707f79c?
    X-Amz-Algorithm=AWS4-HMAC-SHA256&
    X-Amz-Credential=AJAKJFAFGAKAJDDAF
    %2Fus-east-1%2Fs3%2Faws4_request&
    X-Amz-Date=20170702T000940Z&
    X-Amz-Expires=3600&X-Amz-SignedHeaders=host&
    X-Amz-Signature=QEWKJRQJEWR813247812347FKFS
    KQWREJQ3108418324732o45o1324kldsfjasf
).join

Tenga en cuenta que no debe haber nuevas líneas, espacios en blanco cuando se forma la cadena url. Si quieres nuevas líneas, usa HEREDOC.

Aquí tiene sangría para legibilidad, facilidad de modificación, sin las comillas incómodas y las barras invertidas en cada línea. El costo de unir las cuerdas debe ser insignificante.

 11
Author: Zack Xu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-07 10:52:35

Modificé la respuesta de Zack ya que quería espacios e interpolación pero no nuevas líneas y usé:

%W[
  It's a nice day "#{name}"
  for a walk!
].join(' ')

Donde name = 'fred' esto produce It's a nice day "fred" for a walk!

 6
Author: iheggie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-29 09:36:40