晴耕雨読

work in the field in fine weather and stay at home reading when it is wet

Rubyでヒアドキュメントのインデントを取り除く方法

Rubyでインデントがある状態でヒアドキュメントを作成すると、インデントもヒアドキュメントの一部になってしまうので、 それを取り除くする方法。

解決方法

String に下のような、インデントを取り除く dedent メソッドを定義します。 dedent は de-indent の略です。

class String
  def dedent
    gsub(/^#{scan(/^\s*/).min_by{|l|l.length}}/, "")
  end
end

使い方

上記の dedent メソッドを定義した上で、次のように使います。

class Foo
  def bar
    # 使い方は "str".dedent
    desc = <<-EOS.dedent
      Here documents

      To construct a here document, the << operator is followed by an identifier
      that marks the end of the here document. The end mark is called the terminator.
      The lines of text prior to the terminator are joined together, including
      the newlines and any other whitespace.
    EOS
  end
end

puts Foo.new.bar
# => Here documents
# =>
# => To construct a here document, the << operator is followed by an identifier
# => that marks the end of the here document. The end mark is called the terminator.
# => The lines of text prior to the terminator are joined together, including
# => the newlines and any other whitespace.

追記 2016-09-26

Ruby2.3.0 の Frozen String Literal プラグマ や &. 演算子(Safe navigation operator) の登場によって、影に隠れてしまいましたが … なんと 2.3.0 では、ヒアドキュメントの新しい構文 <<~ が追加されました。

# Ruby2.3.0 以降で動作
class Foo
  def bar
    # 新しい構文 <<~
    desc = <<~EOS
      Here documents

      To construct a here document, the << operator is followed by an identifier
      that marks the end of the here document. The end mark is called the terminator.
      The lines of text prior to the terminator are joined together, including
      the newlines and any other whitespace.
    EOS
  end
end

puts Foo.new.bar
# => Here documents
# =>
# => To construct a here document, the << operator is followed by an identifier
# => that marks the end of the here document. The end mark is called the terminator.
# => The lines of text prior to the terminator are joined together, including
# => the newlines and any other whitespace.

Ruby2.3.0 indented here document