#8 Layouts and content_for
Below we have an application layout file and an index
action:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head> <title>Todo List</title> <%= stylesheet_link_tag 'application' %> </head> <body> <div id="container"> <h1>Todo List</h1> <%= yield %> </div> </body> </html>
application.rhtml[1]
<h2>Projects</h2> <ul> <% for project in @projects %> <li><%= project.name %></li> <% end %> </ul>
index.rhtml [1]
When the index
action is rendered it will be rendered within the layout file. (See the previous episode for more details about layouts). But what if we want more control over the layout and want to customize it based on the template that is being rendered? Let’s say that we want to use a custom CSS file in the index
template. The solution is to use a helper method called content_for
in our template. content_for
takes a symbol as an identifier, in this case :head
, and a block. The code placed inside of the block will be stored for later use and not output inside the template.
<% content_for :head do %> <%= stylesheet_link_tag 'projects' %> <% end %> <h2>Projects</h2> <ul> <% for project in @projects %> <li><%= project.name %></li> <% end %> </ul>
index.rhtml[1]
This change won’t make any difference on its own as we’re not outputting the contents of the content_for
. What we need to do next is to output the content somewhere in the layout. This can be done by calling yield
with the symbol we gave the content_for
. So by adding yield :head
in an ERB block to the head section of our layout, the code within the content_for :head
block in our template will be rendered there.
... <head> <title>Todo List</title> <%= stylesheet_link_tag 'project' %> <%= yield :head %> </head> ...
Looking at the source of the page we can now see the stylesheet reference in our content_for block has been added to the page.
content_for
provides a really useful way of changing the content of a layout dependent on the action. As well as adding stylesheets it can be used to show menus, sidebars or any other content we want only to appear in certain actions.
Notes
- For Rails 2 and above the extension should be
.html.erb
rather than.rhtml
.