how to use content_for so that the content shows up in the layout

akkdio picture akkdio · Jul 20, 2013 · Viewed 15.9k times · Source

Am testing the content_for in my rails 3.2 app and following the rails guides but they are specific to the actual files and I cannot seem to get the yield to work:

application.html.erb file:

 <!DOCTYPE html>
 <html>
<head>
 ...
</head>

<body>




<%= yield :navigation %> #shouldn't this load the content_for block named :navigation specified in the _main_nav.html.erb partial? 

 <%= yield %>  #this load the index page content


</body>
 </html>

I created a layout file _main_nav.html.erb (i know I can render with <%= render 'layouts/header' %> but I am trying to use the content_for instead) The _main_nav.html.erb is:

<% content_for :navigation do %>
<ul>
 <li>Home</li>
 </ul>

<% end %>

They way I read the RailsGuide http://guides.rubyonrails.org/layouts_and_rendering.html#using-the-content-for-method this should work. But it does not. I do not get an error. Seems simple but I am stumped.

When I go to my index.html.erb file I would expect to see this result:

  • Home

Answer

Deej picture Deej · Jul 20, 2013

I believe what you want to have is have a view that will contain your content_for block. So an example would be if you have the following:

index.html.erb

<% content_for :head do %> 
  <%= stylesheet_link_tag 'users' %> 
  #Above this will load the users stylesheet
<% end %> 

<h2>Example</h2> 
  <ul>
    <% @users.each do |users| %> 
      <li><%= user.name %></li>
    <% end %> 
  </ul>

Then to output what inside the users stylesheet we can yield and pass in the symbol of the name of the content_for.

Application.html.erb

    <!-DOCTYPE html> 
      <html> 
        <head> 
         <%= yield :head%>
           <title>This is my title</title 
         </head> 
        <body>
        <p>This is a test</p> 
        <%= yield %> 
     </html> 

So to review whats happening here is that, in my example I am saying I have a users stylesheet that I would like to load into the <head></head> of my application.html.erb. To do this I set the content_for which is a Rails helper and give it the identifier sysmbol which is head which is then called in the application.html.erb where I do yeild :head. So what I am getting my application to do is when the my index.html.erb for that page is being rendered the application.html.erb will load my users stylesheet. Hope this clears things up for you.

Update explanation

To add to this another thing the purpose of combination of using content_for with yield is to allow you to inject data into the application layout from ANY view. So as another example. You could have the following:

<% content_for :title do %> My Title<% end %> 

Here when the controller renders the view template and combines it with the application layout, the text My title will be replaced. The yield(:head) makes it easy to add more elements to the specific page if needed. Take a look at the following example:

app/views/layouts/application.html.erb

<% if content_for?(:navbar) %>
  <%= yield(:navbar) %>
<% else %>
  <%# default navbar %>
  <section class="navbar"></section>
<% end %>

app/views/blah/index.html.erb

<% content_for(:navbar) do %>
  <section class="navbar"></section>
<% end %>

And a further note not sure how your developing your application or what design framework your using but you could also take a look at Rails-Bootstrap-Navbar. May also be an alternative.