ActionText で truncate を使って文章を抜粋する


問題

Rails6 で導入された ActionText で truncate を使いたかったのですが、少し手間取ったのでメモとして残しておきます。
というのも、ActionText では単純にDBに保存されるわけではないからなんですね。

厳密に説明すると長くなるので、使い方とDBについては こちらの記事 が参考にしてください。

やりたいこと

あるモデル(Item)に内容カラム(content)があるとして、その一部のみ(20文字)を表示したいと思います。
また、表示する文章は一行にしたいので、改行と空白は削除します。

(例なので図なんかも表示してみます。)

解決策

というわけで早速解決策です。
なんてことはない、既存のメソッドをただ繋げ併せただけです。

view
strip_tags(@item.content.to_s).gsub(/[\n]/,"").strip.truncate(20)

1つずつメソッドを説明していきます。

@item.content.to_s

content を取得しようとすると、ブラウザ上では登録したままの情報(画像含む)が表示されますが、railsではこんな感じで値を取得されます。

> item.content
=> #<ActionText::RichText id: 1, name: "content", body: #<ActionText::Content "<div class=\"trix-conte...">,
 record_type: "Item", record_id: 1, created_at: "2019-10-21 08:17:41", updated_at: "2019-10-21 08:17:41">

ここで body を使ってしまうと余計な部分もついてきてしまうので、 to_s を使ってhtml部分を取得します。

> item.content.body
=> #<ActionText::Content "<div class=\"trix-conte...">

> item.content.to_s
=> "<div class=\"trix-content\">\n  <div>あいうえおかきくけこさしすせそたちすてとなにぬねの<br><action-text-attachment
 sgid=\"BAh7CEkiCGdpZAY6BkVUSSIvZ2lkOi8vYXBwL0FjdGl2ZVN0b3JhZ2U6OkJsb2IvND9leHBpcmVzX2luBjsAVEkiDHB1cnBvc2U
GOwBUSSIPYXR0YWNoYWJsZQY7AFRJIg9leHBpcmVzX2F0BjsAVDA=--6f463dc7320f7fc75699e62fa71f08fa15e31541\" content-
type=\"image/jpeg\" url=\"http://localhost:3000/rails/active_storage/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJ
BaHBDUT09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--b1c6b5ca78e35a7dd637110d1eaeecf970163b68/icon_test.jpg\"
 filename=\"icon_test.jpg\" filesize=\"6701\" width=\"160\" height=\"144\" presentation=\"gallery\" 
caption=\"アイコン\"><figure class=\"attachment attachment--preview\">\n  <img width=\"160\" height=\"144\" 
src=\"http://localhost:3000/rails/active_storage/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBDUT09IiwiZXhwIj
pudWxsLCJwdXIiOiJibG9iX2lkIn19--b1c6b5ca78e35a7dd637110d1eaeecf970163b68/icon_test.jpg\">\n    <figcaption
 class=\"attachment__caption\">\n      アイコン\n    </figcaption>\n</figure></action-text-attachment><br>
はひふへほまみむめもやいゆえよらりるれろわいうえをん</div>\n</div>\n"

strip_tags(@item.content.to_s)

strip_tags はhtmlタグを削除するメソッドです。

> strip_tags(@item.content.to_s)
=> "\n  あいうえおかきくけこさしすせそたちすてとなにぬねの\n  \n    \n      アイコン\n    \nはひふへほまみむめもやいゆえよらりる
ろわいうえをん\n\n"

図とかが消えて、すっきりしました!
ただ見ていただければわかりますが、まだ \n(改行)空欄 が含まれてしまっていますね。

strip_tags(@item.content.to_s).gsub(/[\n]/,"").strip

gsub メソッドで文中の余計な改行を、 strip で文章前後の空欄を削除します。
今回は全ての改行と文章前後の空欄を削除していますが、文中の空欄も削除する場合は、2つ目のメソッドを使ってください。

> strip_tags(@item.content.to_s).gsub(/[\n]/,"").strip 
=> "あいうえおかきくけこさしすせそたちすてとなにぬねの            アイコン    はひふへほまみむめもやいゆえよらりるれろわいうえを"

> strip_tags(@item.content.to_s).gsub(/[\n," "," "]/,"")
=> "あいうえおかきくけこさしすせそたちすてとなにぬねのアイコンはひふへほまみむめもやいゆえよらりるれろわいうえをん"

strip_tags(@item.content.to_s).gsub(/[\n]/,"").strip .truncate(20)

最後に truncate メソッドで指定文字数分取得します。

> strip_tags(@item.content.to_s).truncate(20)
=> "あいうえおかきくけこさしすせそたち..."

できました!!