Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby Layout Inheritance

I was wondering if there is any layout inheritance implementation in ruby. In symfony, you can do this:

layoutmain.html
Give <head> and all that here
<body>
<h3>{{title}}</h3>

{{block view}}
<div class="row">
<div class="span3">
{{content}}
</div>
</div>

{{end block}}


</body>


layout2.html
{{inherits layoutman}}
{{block view}}
 <div class="container">
Structure it differently
 </div>
{{end block}}

So to speak, it let's you inherit the whole template and override parts for a different layout. So the scripts etc stay as they are in the main template, but you can change the view structure. So you can reuse bits of code in the first layout

I found some liquid inheritance project on github, but it looked outdated

like image 990
SoWhat Avatar asked Oct 21 '22 03:10

SoWhat


1 Answers

I use the following approach to achieve "nesting" of layouts which is the form of layout inheritance that I've found to be most useful.

In the main application helper module app/helpers/application_helper.rb I define a helper method parent_layout:

module ApplicationHelper
  def parent_layout(layout)
    @view_flow.set(:layout, self.output_buffer)
    self.output_buffer = render(:file => layout)
  end
end

This helper is responsible for capturing the output of the current layout and then rendering the specified parent layout with the child layout inserted when the parent yields.

Then in my views I can set up the layout inheritance as follows. I start with my main application layout app/views/layouts/application.html.erb which is the child layout in this configuration:

<div class="content">
  <h1><%= content_for?(:title) ? yield(:title) : 'Untitled' %></h1>
  <div class="inner">
    <%= yield %>
  </div>
</div>
<%= parent_layout 'layouts/container' %>

The call to the helper method parent_layout specifies that application.html.erb is a child layout of container.html.erb. I then define the parent layout app/views/layouts/container.html.erb as follows:

<!DOCTYPE html>
<html>
<head>
  <title>Sample</title>
</head>
<body>
  <%= yield %>
</body>
</html>

The yield in container.html.erb yields to the "derived" (or child) layout application.html.erb, i.e. it inserts the output of rendering application.html.erb into the <body> of container.html.erb. Note that the parent_layout call needs to come at the end of the template since it captures the output of the layout up until the point at which it is invoked.

This is based on this article but updated to work in Rails 3.2 (and, hopefully, later). I haven't tried it in Rails 4, but you'll be able to get something similar working.

like image 147
Richard Cook Avatar answered Nov 03 '22 20:11

Richard Cook