4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Rails の helper でブロックを受け取って、そのブロックの中で render をつかいたい

Last updated at Posted at 2020-02-21

こんなことがしたい(けどうまくいかない)

ブロックを受け取って h1 を出力するヘルパーと、それの使用例

hoge_helper.rb
  def render_h1_with_block(&block)
    content_tag(:h1, yield, class: 'title')
  end
hoge/index.html.erb
<%= render_h1_with_block do %>
  <%= render 'fuga' %>
<% end %>
hoge/_fuga.html.erb
  <span>I am fuga.</span>

これは失敗する。h1 の外側に _fuga.html.erbがレンダリングされてしまっている。 render_h1_with_blockyield したタイミングでレスポンスボディに render 'fuga' の結果が追加されてしまうようだ。

意図しない結果になったindex.html
<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 より引用

hoge_helper.rb
  def render_h1_with_block(&block)
    content_tag(:h1, capture(&block), class: 'title')
  end

公式ドキュメントに従って yieldcapture(&block) に書き換えてみた。

意図通りの結果になったindex.html
<h1 class="title"><span>I am fuga.</span></h1>

うまくいった!

ドキュメント

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?