Memecah string panjang pada banyak baris di Ruby tanpa menghapus baris baru

221

Kami baru-baru ini memutuskan pada pekerjaan saya untuk panduan gaya ruby. Salah satu dekrit adalah bahwa tidak boleh ada garis yang lebih lebar dari 80 karakter. Karena ini adalah proyek Rails, kami sering memiliki string yang sedikit lebih lama - yaitu " Pengguna X ingin mengirimi Anda pesan tentang Thing Y " yang tidak selalu sesuai dengan batas gaya 80 karakter.

Saya mengerti ada tiga cara untuk memiliki string panjang span beberapa baris:

  • HEREDOC
  • % Q {}
  • Rangkaian string aktual.

Namun, semua kasus ini pada akhirnya mengambil lebih banyak siklus perhitungan, yang tampaknya konyol. Rangkaian string jelas, tetapi untuk HEREDOCdan %Qsaya harus menghapus baris baru, melalui sesuatu seperti .gsub(/\n$/, '').

Apakah ada cara sintaksis murni untuk melakukan ini, itu setara dengan hanya memiliki seluruh string pada satu baris? Tujuannya, jelas, untuk tidak menghabiskan siklus tambahan hanya karena saya ingin kode saya sedikit lebih mudah dibaca. (Ya, saya menyadari bahwa Anda harus melakukan banyak pengorbanan ... tetapi untuk panjang tali, ini sepertinya konyol.)

Pembaruan: Garis miring terbalik tidak persis seperti yang saya inginkan karena Anda kehilangan indentasi, yang benar-benar memengaruhi gaya / keterbacaan.

Contoh:

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

Saya menemukan hal di atas agak sulit dibaca.

EDIT : Saya menambahkan jawaban di bawah ini; tiga tahun kemudian kita sekarang memiliki heredoc berlekuk.

chug2k
sumber
Mungkin bernilai saat Anda mempertimbangkan faktor-faktor itu.
Cheezmeister
👎🏼 Tidak jelas apakah Anda ingin menyimpan \nkarakter baris baru atau tidak. Jawaban teratas tidak menyimpannya — namun jawaban Anda tetap. Pertanyaannya mengatakan "tanpa menelanjangi baris baru" - tetapi deskripsi mengatakan "[...] Saya harus menghapus baris baru."
Bryan Dimas

Jawaban:

432

Mungkin ini yang Anda cari?

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

p string # => "line #1line #2line #3"
Jessehz
sumber
4
Hah. ya, itu cukup sempurna. Apakah itu benar-benar melakukan penggabungan di bawah tenda? (menyembunyikan tanda +?)
chug2k
13
Saya cukup yakin bahwa itu bukan; Saya mencoba undef'ing dan mendefinisikan kembali String # + dan sepertinya tidak ada yang dikirim ke sana.
Jessehz
Selain itu, meletakkan senar di samping satu sama lain pada baris yang sama juga berfungsi, tetapi itu tidak terlalu berguna.
Jessehz
3
Saya juga suka solusi Emily. Tetapi untuk beberapa alasan saya lebih nyaman dengan yang ini karena memimpin ruang putih pada baris berikut dapat diindentasi tanpa menebak-nebak diri sendiri.
Amin Ariana
5
Kembali, periksa jawaban Amadan untuk pertanyaan terkait ini . Dia menggunakan bytecode untuk membuktikan itu bukan string yang disatukan tetapi memperlakukannya sebagai satu string yang panjang.
Tom Hundt
55

Anda dapat menggunakan \untuk menunjukkan bahwa setiap baris Ruby berlanjut pada baris berikutnya. Ini juga berfungsi dengan string:

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

puts string.inspect

akan menampilkan "this is a string that spans lines"

Emily
sumber
11
Hah. itu cukup sederhana. well, mungkin terlalu banyak bertanya, tapi saya tidak bisa membuat indentasi pada baris berikutnya. itu akan ideal jika saya bisa mencocokkannya dengan tanda sama dengan.
chug2k
5
Catatan: Anda tidak dapat memiliki ruang putih setelah backslash itu. Itu pasti karakter terakhir.
Julian Mann
3
Lihat jawabannya oleh @Jessehz. Cara untuk memiliki kode yang diformat dengan baik dengan indentasi yang tepat adalah dengan menempatkan setiap baris dalam tanda kutip.
orrd
36

Tiga tahun kemudian, sekarang ada solusi di Ruby 2.3: heredoc berlekuk.

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

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

Lekukan dari lekukan paling sedikit akan dihapus dari setiap baris konten.

chug2k
sumber
29
Untuk orang lain bertanya-tanya: <<~HEREDOCmembuat karakter baris baru, hanya rids dari lekukan. Misalnyaline 1\nline 2\nline 3\n
Bryan Dimas
1
Melucuti baris baru masih akan membutuhkan perhitungan tambahan, meskipun, jenis OP yang tersirat tidak diinginkan.
henrebotha
1
@henrebotha Ya, tetapi OP mengatakan lebih eksplisit mereka menginginkan "setara dengan hanya memiliki seluruh string pada satu baris", yang tidak memerlukan baris baru.
Nick
Jadi Anda secara eksplisit menyatakan dalam pertanyaan Anda bahwa Anda tidak ingin menggunakan heredoc dan harus menghapus baris baru. Jawaban Anda di sini menggunakan heredoc dan mengharuskan "pasca pemrosesan" yang ingin Anda hindari.
lamont
17

Saya mengalami masalah ini ketika saya mencoba menulis url yang sangat panjang, karya-karya berikut.

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

Catatan, tidak boleh ada baris baru, spasi putih saat string url terbentuk. Jika Anda ingin baris baru, maka gunakan HEREDOC.

Di sini Anda memiliki lekukan untuk keterbacaan, kemudahan modifikasi, tanpa tanda kutip dan garis miring terbalik pada setiap baris. Biaya bergabung dengan string harus diabaikan.

Zack Xu
sumber
10

Saya mengubah jawaban Zack karena saya ingin spasi dan interpolasi tetapi tidak baris baru dan digunakan:

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

tempat name = 'fred'ini menghasilkanIt's a nice day "fred" for a walk!

iheggie
sumber