Rails Multipart Layouts and Yielding Sections

Photo by Jackson So on Unsplash

Rails Multipart Layouts and Yielding Sections

Play this article
One of the great strengths of Rails is the ability to create layouts that house various views of content. You create a layout with a basic HTML structure and then simply drop in your new content based on the view you are rendering. One of the simplest layouts is one that just renders the view that takes up the whole page and this is accomplished by the auto generated app/views/layouts/application.html.erb.
<!DOCTYPE html>
<html>
<head>
  <title>Myapp</title>
  <%= stylesheet_link_tag    "application", media: "all", "data-turbolinks-track" => true %>
  <%= javascript_include_tag "application", "data-turbolinks-track" => true %>
  <%= csrf_meta_tags %>
</head>
<body>

<%= yield %>

</body>
</html>
The highlighted line is the important one. That <%= yield %> tells Ruby on Rails that whatever view you load just drop it right there. That's great! Now we have a simple base layout that houses our imports and basic structure and CSS and we simply drop in our own content inside of this. Let's say we want to take it a step further. What if we want a left and a right side bar which is unique to each of our views? We just need to change our basic layout a little bit to add those columns and then update our view template code to take advantage of our new structure.

Yield Sections

app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
<head>
  <title>Myapp</title>
  <%= stylesheet_link_tag    "application", media: "all", "data-turbolinks-track" => true %>
  <%= javascript_include_tag "application", "data-turbolinks-track" => true %>
  <%= csrf_meta_tags %>
</head>
<body>

<div id="left" class="sidebar">
  <%= yield :left %>
</div>

<div id="content">
  <%= yield %>
</div>

<div id="right" class="sidebar">
  <%= yield :right %>
</div>

</body>
</html>
app/views/MODEL/new.html.erb
<% content_for :left do %>
  <h2>Left Side</h2>
  <ul>
    <li>...</li>
  </ul>
<% end %>

<% content_for :right do %>
  <h2>Right Side</h2>
  <ul>
    <li>...</li>
  </ul>
<% end %>

<h1>Content Heading></h1>
Following the suggestion of Obie Fernandez and Kevin Faustino in their book The Rails 4 Way, I have placed the two named structures of the layout first. It makes it easy to distinguish what the smaller sections will contain before getting to the meat of the content. Everything that isn't labeled as content_for will be dropped in that unnamed yield in the layout.

Render Partials

That's all well and good but what if you don't want a specific set of sidebar content for every single view. Maybe a shared partial for the right bar will work great. In that case you'll need to use the render method in your template to generate the template for you. Here is the example from above but using a shared right side bar template. app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
<head>
  <title>Myapp</title>
  <%= stylesheet_link_tag    "application", media: "all", "data-turbolinks-track" => true %>
  <%= javascript_include_tag "application", "data-turbolinks-track" => true %>
  <%= csrf_meta_tags %>
</head>
<body>

<div id="left" class="sidebar">
  <%= yield :left %>
</div>

<div id="content">
  <%= yield %>
</div>

<div id="right" class="sidebar">
  <%= render 'shared/right' %>
</div>

</body>
</html>
app/views/shared/_right.html.erb
<h2>Right Side</h2>
<ul>
  <li>...</li>
</ul>

Render Partials with Variables

You can even pass in variables to your partials. Let's say our right side bar takes advantage of some user data. We just pass the user variable to the render with a comma and a hash type variable being passed. app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
<head>
  <title>Myapp</title>
  <%= stylesheet_link_tag    "application", media: "all", "data-turbolinks-track" => true %>
  <%= javascript_include_tag "application", "data-turbolinks-track" => true %>
  <%= csrf_meta_tags %>
</head>
<body>

<div id="left" class="sidebar">
  <%= yield :left %>
</div>

<div id="content">
  <%= yield %>
</div>

<div id="right" class="sidebar">
  <%= render 'shared/right', user: user %>
</div>

</body>
</html>
app/views/shared/_right.html.erb
<h2>Right Side</h2>
<h3><%= user.name %></h3>
<ul>
  <li>...</li>
</ul>
Pretty cool, right? I hope this introduction to layouts and partials was helpful. If there are any problems with my examples or if you have any questions please feel free to leave a comment below.