Beware rendering multiple partials with layouts

Want to render more than one partial with the same layout in your page? Beware:

<%= render :partial => 'p1', :layout => 'layouts/p_layout' %>
<%= render :partial => 'p2', :layout => 'layouts/p_layout' %>

layouts/p_layout.html.erb

<%= yield :top %>
<%= yield %>
<%= yield :bottom %>
<hr/>

_p1.html.erb

<% content_for :top, 'HeaderFor1' %>
<% content_for :bottom, 'FooterFor1' %>
Content!

_p2.html.erb

<% content_for :top, 'HeaderFor2' %>
<% content_for :bottom, 'FooterFor2' %>
Content!

Did you expect this?

<p>
HeaderFor1 Content! FooterFor1
<hr/>
HeaderFor2 Content! FooterFor2
<hr/>
</p>

Nope. You get this:

<p>
HeaderFor1 Content! FooterFor1
<hr/>
HeaderFor1HeaderFor2 Content! FooterFor1FooterFor2
<hr/>
</p>

The instance variables in the layout object retain their values, even between invocations of render. My workaround (since I’m not sure if some would call this a “feature”)…clear the instance variables at the end of your layout.

<%= yield :top %>
<%= yield %>
<%= yield :bottom %>
<hr/>
<% @content_for_top, @content_for_bottom = nil %>

Now it works as I expected.