Help us understand the problem. What is going on with this article?

RailsでのHTML生成は、Nokogiri::HTML::Builderを使えばキレイに書ける(かも)

More than 3 years have passed since last update.

最近、Rails製自社サービスのリファクタリングとして、viewに書いていたロジックをdecoratorに移行させる作業を行っているのですが、htmlタグの生成方法に悩んでおります。

content_tagは使いたくない

Railsには、htmlタグを生成する汎用的なヘルパーメソッドとして、"content_tag" があります。

例えば以下のような感じでhtmlを生成することができます。

content_tag(:div) do
  concat content_tag(:h3, 'タイトル')
  concat content_tag(:p, 'テキスト')
  concat(
    content_tag(:ul) do
      concat content_tag(:li, 'リスト1')
      concat content_tag(:li, 'リスト2')
      concat content_tag(:li, 'リスト3')
    end
  )
end

<div>
  <h3>タイトル</h3>
  <p>テキスト</p>
  <ul>
    <li>リスト1</li>
    <li>リスト2</li>
    <li>リスト3</li>
  </ul>
</div>

便利なメソッドではあるのですが、htmlの構造が複雑になるにしたがって、非常に見づらいし助長な感じになってしまいます。

nokogiriのHtmlBuilderを使えばキレイに書けそう

様々な手段を検討してみたのですが、nokogiriのHtmlBuilderを使うのがベターだと感じました。
HtmlBuilderを使えば、上記のhtmlを、以下のように記述することができます。

root = Nokogiri::HTML::DocumentFragment.parse('')
Nokogiri::HTML::Builder.with(root) do |t|
  t.div do
    t.h3 'タイトル'
    t.p 'テキスト'
    t.ul do
      t.li 'リスト1'
      t.li 'リスト2'
      t.li 'リスト3'
    end
  end
end

構造が分かりやすく、非常に読みやすいです。

モジュールにラップして使う

自社サービスに適用することを想定して、モジュール化してみます。

module HtmlBuilder
  def to_html
    root = Nokogiri::HTML::DocumentFragment.parse('')
    Nokogiri::HTML::Builder.with(root) do |tag|
      yield tag
    end

    root.to_html.html_safe
  end
end

そして、decoratorとかの中で呼び出します。

def tableA_tag
  to_html do |t|
    t.div do
      t.h3 'タイトル'
      t.p 'テキスト'
      t.ul do
        t.li 'リスト1'
        t.li 'リスト2'
        t.li 'リスト3'
      end
    end
  end
end

class指定方法が便利

HtmlBuilderで生成するtagにclassを指定すには、2通りの方法があります。

まずは普通に、

t.h3 'タイトル', class: 'class_name'

とかする方法です。もう一つはtag名の後に直接追加する方法で、

t.h3.class_name 'タイトル'

こんな感じでも記述できます。
これなら、slimやhamlの記述方法とほぼ同じなので、とても直感的で無駄がありません。

最後に

nokogiriはhtmlスクレイパーとして有名ですが、htmlビルダーとしてはあまり知られていないのでしょうか。ググって見たのですが、HtmlBuilderの情報は想像以上に少なかったです。個人的にはとても便利だと思ったのですが、何か欠点とかあるのかしら?

EastResident
webの会社でアドテクエンジニア?やってます。しばらくはGCP中心に書く予定。
https://eastresident.hatenablog.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away