ruby-on-railsruby-on-rails-6actionviewactionviewhelper

Rails yield and content_for wieird behaviour, `yield :filter` only work if placed after default yield


Lets say i have this partial i am trying to render

#layouts/_subheader.html.erb
<div class="subheader">
   <%= yield %>
   <%= yield :filters %>
</div>

when i use this partial in a view like this

<%= render 'layouts/sub_header' do %>
   <h2> Content For Yield </h2>
   <% content_for :filters do %>
      <h2> Content for Filters </h2>
   <%  end %>
<% end %>

i am getting the HTML output as

<div class="subheader">
   <h2> Content For Yield </h2>
   <h2> Content for Filters </h2>
</div>

this works as expected, but the problem arises when i change the order of the yield tags in the partial

instead of the above, if i rewrite the partial as

#layouts/_subheader.html.erb
<div class="subheader">
   <%= yield :filters %>
   <%= yield %>
</div>

i am getting output as

<div class="subheader">
   <h2> Content For Yield </h2>
</div>

the content_for :filters is not being rendered.

what an i doing wrong here ? is this the correct behavior or am i doing something wrong ?

what should i do if i have to make the content of the yield :filters appear before the plain yield

EDIT:-

I have tried

#layouts/_subheader.html.erb
<div class="subheader">
   <%= content_for :filters %>
   <%= yield %>
</div>

but it seems to be not working as well.


Solution

  • Thanks everyone on reddit and @Ezhil i found a solution, this is what i did

    what i did is i placed the content_for capture group before the render like this

    #index.html.erb
    <% content_for :filters do %>      
      <h2> Content for Filters </h2> 
    <% end %> 
    
    <%= render 'layouts/sub_header' do %>   
      <h2> Content For Yield </h2> 
    <% end %>
    

    and in my partial

    #layouts/_subheader.html.erb 
    <div class="subheader">     
       <%= content_for :filters %>     
       <%= yield %>
    </div>
    

    It's because the block isn't executed until the first yield, so there's no content captured until that runs.