content_tagへの不満
私が今関わっているRails製サービスでは、viewに直接ロジックが書かれている部分が多いため、helperやdecoratorに処理の移行を進めています。しかし、うちのチームにはRails有識者がいないため、view生成周りのベストプラクティスが分かりません。今日はcontent_tagの使い方で悩みました。
例えば、以下のようなhtmlがあるとします。
<div>
<h3>タイトル</h3>
<p>テキスト</p>
<ul>
<li>リスト1</li>
<li>リスト2</li>
<li>リスト3</li>
</ul>
</div>
これを、単純にcontent_tagで生成するとしたら、以下のように書けます。
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
特定のタグ配下にに複数の要素を挿入する場合は、ブロック内でconcatに渡します。
しかし、ここで些細な問題が発生します。それは・・・
concatにブロック付きのcontent_tagを渡すには、カッコで囲まなければいけない
ということです。以下の部分ですね。
concat(
content_tag(:ul) do
~中略
end
)
この記法は非常に見づらいので、できるなら使いたくありません。
どうすれば?
ケースバイケースなので最適解はないかもしれませんが、自分が思いついたのは次のような方法です。
まず、ブロック付きで呼び出すcontent_tagに代わるメソッドを定義します。
def content_tag_push(type, *option)
tags = []
yield tags
content_tag(type, tags.reduce(:+), *option)
end
先ほどの例を、上記のメソッドを使って置き換えると以下のようになります。
content_tag_push(:div) do |div|
div << content_tag(:h3, 'タイトル')
div << content_tag(:p, 'テキスト')
div << content_tag_push(:ul) do |ul|
ul << content_tag(:li, 'リスト1')
ul << content_tag(:li, 'リスト2')
ul << content_tag(:li, 'リスト3')
end
end
個人的にはこちらのほうが統一感があって好きなのですが、どうなのでしょう・・・
最後に
もっとマシな方法がある気がします。そもそも、ネストが深い場合は適度に処理を分けるべきなので、こんなこと真面目に考える必要ないかも。