Rompere lunghe stringhe su più linee in Ruby senza mettere a nudo le nuove linee


221

Di recente, nel mio lavoro, abbiamo deciso di fare una guida allo stile rubino. Uno degli editti è che nessuna linea dovrebbe essere più larga di 80 caratteri. Dato che si tratta di un progetto Rails, spesso abbiamo stringhe un po 'più lunghe, ovvero "L' utente X voleva inviarti un messaggio su Thing Y " che non rientra sempre nel limite dello stile di 80 caratteri.

Capisco che ci sono tre modi per avere una stringa lunga su più righe:

  • heredoc
  • % Q {}
  • Concatenazione di stringhe effettiva.

Tuttavia, tutti questi casi finiscono per richiedere più cicli di calcolo, il che sembra sciocco. Concatenazione di stringhe ovviamente, ma per HEREDOCe %Qdevo eliminare le nuove righe, tramite qualcosa di simile .gsub(/\n$/, '').

Esiste un modo di sintassi puro per fare ciò, che equivale a avere l'intera stringa su una riga? L'obiettivo è, ovviamente, di non spendere altri cicli solo perché voglio che il mio codice sia leggermente più leggibile. (Sì, mi rendo conto che devi fare molto quel compromesso ... ma per la lunghezza della corda, questo sembra sciocco.)

Aggiornamento: le barre rovesciate non sono esattamente ciò che voglio perché perdi il rientro, il che influisce davvero sullo stile / leggibilità.

Esempio:

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

Trovo quanto sopra un po 'difficile da leggere.

EDIT : ho aggiunto una risposta di seguito; tre anni dopo ora abbiamo l'ereditarietà agitata.


Potrebbe valere la pena dedicare un po 'di tempo a queste stringhe.
Cheezmeister,


👎🏼 Non è chiaro se si desidera mantenere \no meno i caratteri di nuova riga. La risposta migliore non li mantiene, eppure la tua risposta lo fa. La domanda dice "senza togliere le righe", ma la descrizione dice "[...] devo eliminare le righe".
Bryan Dimas,

Risposte:


432

Forse questo è quello che stai cercando?

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

p string # => "line #1line #2line #3"

4
eh. sì, è abbastanza perfetto. sta davvero facendo un concatenato sotto il cofano? (nascondendo un +?)
chug2k

13
Sono abbastanza sicuro che non lo sia; Ho provato sia indefinendo che ridefinendo String # + e non sembra che ci sia stato inviato nulla.
Jessehz,

Inoltre, anche mettere le stringhe una accanto all'altra sulla stessa linea funziona, ma non è molto utile.
Jessehz,

3
Mi piace anche la soluzione di Emily. Ma per qualche motivo mi sento più a mio agio con questo perché gli spazi bianchi iniziali sulle seguenti righe possono essere rientrati senza indovinarsi.
Amin Ariana,

5
Per quanto riguarda la concatenazione, controlla la risposta di Amadan a questa domanda correlata . Usa il bytecode per dimostrare che non sta concatenando le stringhe ma trattandole come una lunga.
Tom Hundt,

55

Puoi usare \per indicare che qualsiasi linea di Ruby continua sulla riga successiva. Funziona anche con le stringhe:

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

puts string.inspect

uscirà "this is a string that spans lines"


11
eh. è piuttosto semplice. bene, probabilmente è troppo da chiedere, ma non riesco a rientrare nella riga successiva. sarebbe l'ideale se potessi abbinarlo al segno uguale.
chug2k,

5
Nota: non è possibile avere spazi bianchi dopo quella barra rovesciata. Deve essere l'ultimo personaggio.
Julian Mann,

3
Vedi la risposta di @Jessehz. Il modo per avere un codice ben formattato con il rientro corretto è mettere ogni riga tra virgolette.
or

36

Tre anni dopo, ora c'è una soluzione in Ruby 2.3: l'erede selvaggia.

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

Link al post sul blog: https://infinum.co/the-capsized-eight/articles/multiline-strings-ruby-2-3-0-the-squiggly-heredoc

Il rientro della riga meno rientrata verrà rimosso da ciascuna riga del contenuto.


29
Per chiunque si stia chiedendo: <<~HEREDOCmantiene i personaggi newline, elimina solo il rientro. Ad esempioline 1\nline 2\nline 3\n
Bryan Dimas,

1
Spogliare le nuove linee richiederà comunque un calcolo extra, cosa che il tipo di OP implicito non era desiderabile.
henrebotha,

1
@henrebotha Sì, ma OP ha detto più esplicitamente di voler "l'equivalente di avere l'intera stringa su una riga", che non richiederebbe nuove righe.
Nick,

Quindi hai esplicitamente dichiarato nella tua domanda che non volevi usare un heredoc e che devi eliminare le nuove righe. La tua risposta qui usa una eredità e richiede quella "post-elaborazione" che volevi evitare.
Lamont,

17

Ho avuto questo problema quando provo a scrivere un URL molto lungo, i seguenti lavori.

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=ABABABABABABABABA
    %2Fus-east-1%2Fs3%2Faws4_request&
    X-Amz-Date=20170702T000940Z&
    X-Amz-Expires=3600&X-Amz-SignedHeaders=host&
    X-Amz-Signature=ABABABABABABABABABABAB
    ABABABABABABABABABABABABABABABABABABA
).join

Nota, non devono esserci newline, spazi bianchi quando si forma la stringa dell'URL. Se vuoi newline, usa HEREDOC.

Qui hai un rientro per leggibilità, facilità di modifica, senza virgolette e barre rovesciate su ogni riga. Il costo di unione delle stringhe dovrebbe essere trascurabile.


10

Ho modificato la risposta di Zack poiché volevo spazi e interpolazione ma non newline e ho usato:

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

dove name = 'fred'questo produceIt's a nice day "fred" for a walk!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.