Nested layouts in Rails 3
Published almost 4 years ago

This an update/rewrite of my previous post nested layouts – as that version no longer works with Rails 3.

Code

def parent_layout(layout)
  @_content_for[:layout] = self.output_buffer
  self.output_buffer = render(:file => "layouts/#{layout}")
end

Add the above helper method in your ApplicationHelper or wherever you see fit.

Example

Let’s say your application has an admin section. And for all the views using admin.html.erb layout, you want to fetch stylesheets, javascript, footer etc. from the application.html.erb layout. One way to do this would be to keep the shared code in partials. However, using inheritance style layouts feels more natural to me.

Here’s how you can use application.html.erb as the layout for the admin.html.erb layout :

# layouts/admin.html.erb
<h1>Admin Panel</h1>
<div class="admin_navigation">Home | Posts | Users | Assets</div>
<%= yield %>

<%= parent_layout 'application' %>

Your application.html.erb layout is just another regular layout that can be used independently.

# layouts/application.html.erb
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head><title>Hello World</title></head>
  <body>
    <%= yield %>
  </body>
</html>

Using admin.html.erb layout is now affectively same as using the following layout :

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head><title>Hello World</title></head>
  <body>
    <h1>Admin Panel</h1>
    <div class="admin_navigation">Home | Posts | Users | Assets</div>
    <%= yield %>
  </body>
</html>