ブロックを受け取れるヘルパー

入力フォームがたくさんあるシステムを作ってるとき、コピペしていくよりヘルパーにしちゃった方が楽だろうということで調べてみました。

たとえば単にdivで囲みたいっていうとき

<%= wrap_div("This is content given as parameter") %>
#=> <div>This is content given as parameter</div>

<% wrap_div do %>
  This is content given as block
<% end %>
#=> <div>This is content given as block</div>

のようにメソッドの引数でも渡せるしブロックでも渡せるようにしたい。
こういうときapplication_helper.rbとかに

def wrap_div(content = nil, &block)
  html = "<div>"
  html += content if content
  html += capture(&block) if block_given?
  html += "</div>"
  block_called_from_erb?(block) ? concat(html) : html
end

capture(&block) でブロックの実行結果を文字列で取得する
block_called_from_erb?(block) でブロックの有無を判別。ある場合は concat(html) でバッファに出力する。ない場合はそのままhtmlを返す。
これでできました。

#スーパーpreってすごい便利だけど行番号も出ればもっといいのになぁ