[Ruby on Rails] 文字列に含まれる改行・URL・メールアドレスをHTMLのタグに変換する

Webアプリを作っているとユーザの投稿などを表示する際に入力と同様の改行を入れて表示したり、URLやメールアドレスをリンクにしたいというケースがそれなりにあります。 そのまま表示してしまうと、改行はHTMLのソース上で改行されますが、表示上は改行されません。 URLやメールアドレスもそのまま表示されるため、リンクにはならず、当然クリックしても何も起きません。 そのため入力と同様の改行やURL・メールアドレスのリンク化はそれぞれの文字列をHTMLのタグに置換する必要があります。

このような機能を持つgemもありますが、「gemを入れるほどの機能ではない」「安易にライブラリを増やしたくない」という理由からいつも以下のヘルパーモジュールをapp/helpersに入れています。

module UserTextHelper
  def user_text(text)
    return if text.blank?

    raw(email2a(url2a(nl2br(sanitize(text).to_s))))
  end

  def nl2br(text)
    text.gsub(/\R/) { %Q{<br>} }
  end

  def url2a(text)
    text.gsub(URI.regexp(%w[http https])) { %Q{<a href="#{$&}" target="_blank">#{$&}</a>} }
  end

  def email2a(text)
    text.gsub(/[\w+\-.]+@[a-z\d\-.]+\.[a-z]+/i) { %Q{<a href="mailto:#{$&}">#{$&}</a>} }
  end
end

処理内容は単純で以下のようになっています。

  1. 元の文字列をsanitizeする(rawメソッドを利用するため予めsanitizeする必要があります)
  2. 改行文字をbrタグに置換
  3. URLをaタグに置換
  4. メールアドレスをaタグに置換
  5. 変換したタグがエスケープされないようにrawでhtml_safeして返す

あとはviewで投稿内容などの対象文字列をuser_textヘルパーを利用して表示します。

<div class="post">
  <%= user_text(@post.body) %>
</div>