改行コードを<br>タグに変換して表示する

背景

今までtextareaで受け取った文字列をそのままhtmlに埋め込んで表示していた。これだと改行が反映されないので困っていた。

解決策

文字列の置換

gsub関数

コントローラで文字列を置換することにした。Rubyでは、文字列の置換をgsub関数で行う。改行コードの一括置換は次のように行う。

test.gsub(/\R/, "<br>")

ここで \R は改行コードを表すメタ文字。このようにして改行コードを一括で<br>タグに変換した。

参考文献
文字列中の改行コードを統一する - Qiita

HTMLタグのエスケープの回避

このままでは、<br>タグがエスケープされる。

html_safe

text.html_safe

こうすると、タグのエスケープが行われなくなる。ただし、<script>グもそのままになるので、XSSが怖い(他にもいろいろあるかも)

参考文献
HTML特殊文字のエスケープ - Ruby on Rails入門

sanitize

erbファイルで次のように記述する。

sanitize(text, tags: %w(br))

こうすると、<br>タグのみエスケープされなくなる。これで安心。

参考文献
sanitize | Railsドキュメント

成果物の一部(自分用メモ)

詳細はGitHub

show.html.erb(sanitizeの使用例)

<div data-controller="show">
<ul data-action="show#content">
  <% @post.errors.full_messages.each do |message| %>
    <li>
      <%= message %>
    </li>
  <% end %>
</ul>
<h2><%= @post.title %></h2>
<h3><%= @post.created_at %></h3>
<p><%= link_to("編集", "/posts/#{@post.id}/edit") %></p>
<p data-action="click->show#confirm"><%= link_to("削除", "/posts/#{@post.id}/destroy", data: {confirm: "a", turbo_method: :post}) %></p>
<p><%= sanitize(@content, tags: %w(br)) %></p>
<p><%= link_to("記事一覧へ", "/posts/index") %>
</div>

post_controller.rbの一部(gsubの使用例)

  def show
    @post = Post.find_by(id:params[:id])
    @content = @post.content
    @content = @content.gsub(/\R/,"<br>")
  end