こんなことがしたい(けどうまくいかない)
ブロックを受け取って h1
を出力するヘルパーと、それの使用例
def render_h1_with_block(&block)
content_tag(:h1, yield, class: 'title')
end
<%= render_h1_with_block do %>
<%= render 'fuga' %>
<% end %>
<span>I am fuga.</span>
これは失敗する。h1
の外側に _fuga.html.erb
がレンダリングされてしまっている。 render_h1_with_block
で yield
したタイミングでレスポンスボディに render 'fuga'
の結果が追加されてしまうようだ。
<span>I am fuga.</span>
<h1 class="title"></h1>
解決策: capture
を使う
CaptureHelper#capture
をつかって render の結果を保留すればうまくいく。
The capture method extracts part of a template as a
String
object. You can then use this object anywhere in your templates, layout, or helpers.
(適当な翻訳) capture
メソッドはテンプレートの一部を String
オブジェクトとして切り出します。そのオブジェクトはテンプレート、レイアウト、ヘルパーで利用できます。
ActionView::Helpers::CaptureHelper#capture - Ruby on Rails API Document より引用
def render_h1_with_block(&block)
content_tag(:h1, capture(&block), class: 'title')
end
公式ドキュメントに従って yield
を capture(&block)
に書き換えてみた。
<h1 class="title"><span>I am fuga.</span></h1>
うまくいった!