LandonSchropp
LandonSchropp

Reputation: 10244

Nesting layouts in Rails

Is it possible to nest layouts in Rails 3.2? I'd like to create a generic layout used by application.html.erb and allow a couple views in the application to use it. I found the Nested Layouts ruby gem, but it hasn't been updated in four years. It would be awesome if I could do something like the following in my application.html.erb file:

<% inside_layout 'html5_boilerplate' do %>
  <div id="container">
    <%= yield %>
  </div>
<% end %>

Upvotes: 5

Views: 2242

Answers (4)

BvuRVKyUVlViVIc7
BvuRVKyUVlViVIc7

Reputation: 11811

You can use the content_for method as described in the official Rails guide.

Upvotes: 1

flintinatux
flintinatux

Reputation: 409

I tried a few of these, but none worked for me in Rails 4. But with a little inspiration from the nested_layouts gem, I came up with the following simple fix:

module ApplicationHelper
  def inside_layout(layout, &block)
    layout = "layouts/#{layout}" unless layout =~ %r[\Alayouts/]
    content_for :content, capture(&block)
    render template: layout
  end
end

Then I revised my layouts/application.html.erb template to be similar to this:

<html>
  <body>
    <div id="content">
      <%= content_for?(:content) ? yield(:content) : yield %>
    </div>
  </body>
</html>

Now I can declare a nested layout like this:

# app/views/layouts/blog.html.erb
<%= inside_layout 'application' do %>
  <div id="blog_container">
    <%= yield %>
  </div>
<% end %>

Hope this helps!

Upvotes: 5

LandonSchropp
LandonSchropp

Reputation: 10244

I found an easy solution in this blog post.

In my ApplicationHelper, I added the following:

def parent_layout(layout)
  @view_flow.set(:layout, output_buffer)
  self.output_buffer = render(:file => "layouts/#{layout}")
end

In application.html.erb, I added:

<% parent_layout 'html5_boilerplate' %>

Upvotes: 11

rwheadon
rwheadon

Reputation: 241

AFAIK Your application layout is going to surround everything in your app. so really just build those partials into the relationships you have on the individual view level.

I have a person object that has some other parts of the model included in their partial render in a div like below. It's not pretty but it hopefully is along the lines of what you want to accomplish.

<div id="div-1">
    <fieldset><legend><b>Registrant Information</b></legend>
        <fieldset><legend><b>Personal Information</b></legend>
          <p class="field">
            <%= f.label "First Name" %>
            <%= f.text_field :firstname %>
        &nbsp;&nbsp;
            <%= f.label "Last Name" %>
            <%= f.text_field :lastname %>
        &nbsp;&nbsp;
            <%= f.label "Middle Init" %>
            <%= f.text_field :middleinit, :size=>2 %>
        &nbsp;&nbsp;
            <%= f.label "Nickname" %>
            <%= f.text_field :nickname %>
            </p> 
          <p class="field"> 
            <%= f.label :birthdate %>
            <%= f.date_select :birthdate, :start_year=>1935%>
        &nbsp;&nbsp;
            <%= f.label :gender %>
            <%= f.select :gender, ['Male','Female'] %>
            </p> 
          <p class="field">
            <%= f.label "T-Shirt Size" %><br />
            <%= f.select :shirtsize, ['YS','YM','YL','S','M','L','XL','XXL'] %>
            </p>
        </fieldset><br/>
        <fieldset><legend><b>Address Information</b></legend>
          <%= f.fields_for :addresses do |builder| %>
            <%= render "address_fields", f: builder %>
          <% end %>
        </fieldset>
        <fieldset><legend><b>Email</b></legend>
            <%= f.fields_for :emails do |builder| %>
                <%= render "email_fields", f: builder %>
            <% end %>
            <%= link_to_add_fields "Add Email", f, :emails %>
        </fieldset>
    </fieldset>    
</div>

Upvotes: 0

Related Questions