Post

provide と content_for、Streaming(viewとlayoutの評価順)について

動的タイトルを出力するため、content_forを使うのがよく見かけるけど、Rails Tutorialの中に、provideメソッドを推奨しているそう。

Railsでの開発経験者であれば、この時点でcontent_forを検討すると思いますが、残念ながらAsset Pipelineと併用すると正常に動作しないことがあります。provideメソッドはcontent_forの代替です。

Rails APIでの説明では、

provide(name, content = nil, &block) The same as content_for but when used with streaming flushes straight back to the layout. In other words, if you want to concatenate several times to the same buffer when rendering a given template, you should use content_for, if not, use provide to tell the layout to stop looking for more contents.

またStreamingについては、

By default, Rails renders views by first rendering the template and then the layout. The response is sent to the client after the whole template is rendered, all queries are made, and the layout is processed.

Streaming inverts the rendering flow by rendering the layout first and streaming each part of the layout as they are processed. This allows the header of the HTML (which is usually in the layout) to be streamed back to client very quickly, allowing JavaScripts and stylesheets to be loaded earlier than usual.

なるほど。Railsでは、デフォルトでveiwのtemplateを先に評価してから、layoutを評価する。

そして全部の内容をユーザーにレンダリングする。

だた、もしDBクエリが多いアクションを含めた場合、templateを評価するのは時間がかかるため、先にlayoutをレンダリングして、ページタイトルなどの基本内容をユーザーに表示させる方法はstreaming.

content_forは、同じtemplateに複数併用が可能なので、Railsはtemplateを上から下まで評価して、複数のcontent_forを評価して、内容を連結する

1
2
3
<%= content_for :title, "Hello" %>
    <h1>BOARD APP</h1>
  <%= content_for :title, "World" %>

content_forの内容は連結されるので、表示されるタイトルはHelloWorld | OARD APPになる つまり<title>HelloWorld | RUNTEQ BOARD APP</title>

一方で、provideの場合は、複数使うのが不可で、最初のprovideのみが評価される

1
2
3
<% provide :title, "Hello" %>
    <h1>RUNTEQ BOARD APP</h1>
  <% provide :title, "World" %>

上記では、最初のprovideの内容のみが評価される つまり<title>Hello | BOARD APP</title>

結論

providecontent_for は基本的には同じだけど、

もしDB操作が多くて、viewのtemplateが重たいなどの理由で、streamingを使いたい場合、provideを使うのが良い。

そうすると、template最初のprovide部分のみを評価して、残りの部分を置いといて、layoutのところに戻る。

残り疑問

「content_forはAsset Pipelineと併用すると正常に動作しないことがある」と言うのはどういう場合?


参照: Rails tutorial Rails API Streamingとは AssetPipelineとは railsのアセットパイプラインについて解説する Ruby on Rails: provide vs content_for Railsのviewとlayoutの評価順についてコードを読んで納得した

This post is licensed under CC BY 4.0 by the author.