New bamboo web development

Bamboo blog. Our thoughts on web technology.


Nested layouts in Merb

almost 4 years agoby Martyn Loughran

First a simple solution using throw_content and catch_content.

This is what sublayout.html.erb looks like

 1 <% throw_content :sublayout do %>
 2   <div class="header">
 3     ...
 4   </div>
 5 
 6   <%= catch_content :for_layout %>
 7 
 8   <div class="footer">
 9     ...
10   </div>
11 <% end %>
12 
13 <%= render catch_content(:sublayout), :layout => "application" %>

Your main layout contains <%= catch_content :for_layout %> as usual.


You might find it handy to use catch and throw content in a few more places. For example, in your sublayout you could <%= catch_content :sublayout_title %> and throw it in the view with

1 <% throw_content :sublayout_title %>
2   Hippos
3 <% end %>

As a little bonus I wrote a helper so that you can use the same syntax as you're used to from the rails plugin. Just add this snippet into Merb::GlobalHelpers

1 def inside_layout(layout, &block)
2   content = render(capture(&block), :layout => layout)
3   concat(content, block.binding)
4 end

Then your sublayout looks like

 1 <% inside_layout :sublayout do %>
 2   <div class="header">
 3     ...
 4   </div>
 5 
 6   <%= catch_content :for_layout %>
 7 
 8   <div class="footer">
 9     ...
10   </div>
11 <% end %>

Here's another idea which I think would be even better: What if you could say layout ['application', 'sublayout'] in your controller and have each layout rendered inside it's parent all up the chain? Then sublayout.html.erb wouldn't be constrained to always render inside application.html.erb and you could use it in a much more flexible way. However Damien things it's a mad idea. What do you think?