Hit the books!!

プログラミング学習記録

simple_formatメソッドでtextareaの改行を反映させる

Railsアプリケーションでtext_areaを使うときにお世話になったsimple_formatメソッドについて簡単に調べました。

参考:ActionView::Helpers::TextHelper

「現場で使えるRuby on Rails 5 速習実践ガイド」のtaskleafアプリケーションの例

今「現場で使えるRuby on Rails 5 速習実践ガイド」を読み返していて、113ページに出てくるのでこの内容にそって確認することにします。

タスク管理アプリケーションtaskleafの詳細(description)でsimple_formatが出てきます。show画面で内容を表示したいときに、

# app/views/tasks/show.html.slim

h1 Task Details

.nav
  = link_to 'back to List', tasks_path, class: 'nav-link'
table.table.table-hover
  tbody
    tr
      th= Task.human_attribute_name(:name)
      td= @task.name
    tr
      th= Task.human_attribute_name(:description)
      td= @task.description
    tr
      th= Task.human_attribute_name(:created_at)
      td= @task.created_at
    tr
      th= Task.human_attribute_name(:updated_at)
      td= @task.updated_at

こんな感じで書くと、text_areaの中の改行が反映されずにこうなる↓

f:id:ud_ike:20220228140839p:plain

ほんとは

aaa
bbb

みたいに改行してるんだけど。

そこでsimple_formatですよ。@task.descriptionのところを次のように書き換えると、

    tr
      th= Task.human_attribute_name(:description)
      td= simple_format(h(@task.description), {}, sanitize: false, wrapper_tag: 'div')

ちゃんと改行が反映される。

f:id:ud_ike:20220228142522p:plain

最初の状態

この状態で

      td= @task.description

DevToolsのElementsでHTMLを確認すると、

<td>aaaa
bbbb</td>

こうなってる。

simple_formatでpタグで囲む

simple_formatを使って書き換えると、

      td= simple_format(@task.description)
<td><p>aaaa
<br>bbbb</p></td>

こうなる。simple_formatメソッドはデフォルトで<p>タグで囲ってくれます。

sanitizeオプション

sanitizeオプションをtrueにすると、テキストに含まれる一部のセキュリティ面で危険なHTMLタグを取り除いてくれる。

今回のtaskleafアプリケーションでは、一部のタグを取り除くのではなくすべてのタグを安全に表示させたいのでsanitizeはfalseにしてhメソッドを使う。

hメソッド(html_escapeメソッド)

html_escapeメソッドのエイリアスで、<&lt:などに変換する。

参考:ERB::Util

エスケープしなくない場合はString#html_safeやrowヘルパーを使うとスキップできるとのこと。また、Slimでは==で展開してもエスケープされない。

html_safeとhtml_escapeが混乱するぜ...

wratter_tagオプション

taskleafアプリケーションでは、デザインの都合で<p>タグではなく<div>タグを使いたいので wrapper_tagオプションにdivを設定している。

h1 Task Details

.nav
  = link_to 'back to List', tasks_path, class: 'nav-link'
table.table.table-hover
  tbody
    tr
      th= Task.human_attribute_name(:name)
      td= @task.name
    tr
      th= Task.human_attribute_name(:description)
      td= simple_format(h(@task.description), {}, sanitize: false, wrapper_tag: 'div')
    tr
      th= Task.human_attribute_name(:created_at)
      td= @task.created_at
    tr
      th= Task.human_attribute_name(:updated_at)
      td= @task.updated_at

こうなった!

<div>aaaa
<br>bbbb</div>

めでたしめでたし。