Розривання довгих рядків на декількох рядках у Ruby, не знімаючи нових рядків


221

Нещодавно ми вирішили на моїй роботі керівника по стилю рубін. Один із редакцій полягає в тому, що жоден рядок не повинен бути ширшим за 80 символів. Оскільки це проект Rails, у нас часто є рядки, які трохи довші - тобто " Користувач X хотів надіслати вам повідомлення про Thing Y ", який не завжди входить у межу стилю 80 символів.

Я розумію, що існує три способи мати довгий рядок з декількома рядками:

  • HEREDOC
  • % Q {}
  • Фактичне з'єднання рядків.

Однак усі ці випадки закінчуються більш великими циклами обчислень, що здається дурним. Об'єднання рядків , очевидно, але HEREDOCі %Qя повинен вичистити новий рядок, через що - щось на зразок .gsub(/\n$/, '').

Чи є чистий синтаксичний спосіб зробити це, що еквівалентно простому цілому рядку в одному рядку? Мета, очевидно, не витрачати зайвих циклів лише тому, що я хочу, щоб мій код був трохи читабельнішим. (Так, я розумію, що ви повинні зробити цей компроміс дуже багато ... але для довжини струни це просто здається дурним.)

Оновлення: зворотна коса - це не саме те, що я хочу, тому що ви втрачаєте відступ, що дійсно впливає на стиль / читабельність.

Приклад:

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

Мені сказане трохи важко читати.

EDIT : я додав відповідь нижче; через три роки ми тепер маємо кричущий гередок.


Можливо, варто витратити час на те, щоб вирівняти ці рядки.
Чизмайстер


👎🏼 Незрозуміло, хочете ви зберегти \nсимволи нового рядка чи ні. Верхня відповідь не тримає їх - все ж ваша відповідь є. Питання говорить "не знімаючи нових рядків" - але в описі йдеться "[...] Я повинен викреслити нові рядки".
Брайан Дімас

Відповіді:


432

Може це саме те, що ви шукаєте?

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

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

4
так. так, це досить ідеально. це те, що насправді роблять конкатенат під кришкою? (приховування +?)
chug2k

13
Я досить впевнений, що це не так; Я спробував і відміняти, і переосмислити рядок # +, але, схоже, нічого там не надсилається.
Jessehz

Крім того, розміщення рядків поруч з одним рядком також працює, але це не дуже корисно.
Jessehz

3
Мені також подобається рішення Емілі. Але чомусь мені це зручніше, тому що провідні пробіли в наступних рядках можуть бути відступними, не повторюючи себе.
Амін Аріана

5
Повторіть зв'язок, ознайомтеся з відповіддю на це питання . Він використовує байт-код, щоб довести, що це не об'єднувальні рядки, а трактує їх як одну довгу.
Том Хундт

55

Ви можете \вказати, що будь-який рядок Ruby продовжується в наступному рядку. Це працює і з рядками:

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

puts string.inspect

виведе "this is a string that spans lines"


11
так. це досить просто. ну, це, мабуть, занадто багато запитати, але я не можу відступити наступний рядок. було б ідеально, якби я міг зіставити це зі знаком рівності.
chug2k

5
Примітка: після цього зворотного нахилу не може бути жодного пробілу. Це повинен бути останній персонаж.
Джуліан Манн

3
Дивіться відповідь @Jessehz. Спосіб красиво відформатованого коду з належним відступом - поставити кожен рядок у лапки.
orrd

36

Через три роки в Рубі 2.3 є рішення, яке кричить гередок.

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

Посилання на щоденник: https://infinum.co/the-capsized-eight/articles/multiline-strings-ruby-2-3-0-the-squiggly-heredoc

Відступ найменшого відступу буде видалено з кожного рядка вмісту.


29
Для всіх, хто цікавиться: <<~HEREDOCзберігає символи нового рядка, він лише позбавляє відступу. Напр.line 1\nline 2\nline 3\n
Брайан Дімас

1
Очищення нових рядків все ще потребуватиме додаткових обчислень, що, на думку ОП, мається на увазі, не бажане.
henrebotha

1
@henrebotha Так, але ОП сказала чіткіше, що вони хочуть "еквівалент простому цілому рядку в одному рядку", що не вимагатиме нових рядків.
Нік

Отже, ви прямо сказали у своєму запитанні, що не хочете використовувати гередок і вам доведеться викреслити нові рядки. Ваша відповідь тут використовує гередок і вимагає тієї "післяобробки", якої ви хотіли уникнути.
Ламонт

17

У мене була ця проблема, коли я намагаюся написати дуже довгий URL, наступні твори.

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

Зверніть увагу: при формуванні рядка URL не повинно бути жодних нових рядків, пробілів. Якщо ви хочете нових ліній, тоді використовуйте HEREDOC.

Тут ви маєте відступ для читабельності, простоти модифікації, без чітких лапок та зворотних косих рядків у кожному рядку. Вартість приєднання струн повинна бути незначною.


10

Я змінив відповідь Зака, оскільки хотів пробілів та інтерполяції, але не нових рядків і використовував:

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

де name = 'fred'це виробляєIt's a nice day "fred" for a walk!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.