Hi, I'm Samuel Cochran

on Twitter, Facebook, Google, LinkedIn, GitHub, Stack Overflow, and Steam.

Nice nested layouts

I really wanted a nicer way of doing nested layouts using HAML in Rails. The rails example including yield(:content) || yield makes me want to heave. Okay, so they use content_for? now, but it's still horrid, and what happens when you're more than one or two levels deep?

Ideally, layouts should be able to dictate they inherit from something else. Partially inspired by the NestedLayouts plugin for Rails 2, the best way to do this I could come up is to use a capture block in my layout. This means I can use:

= inside_layout :application do
    %header ...
    = yield

Inside my application layout:

  %head ...
    %header ...
    = yield
    %footer ...

and now use layout :admin in my admin controllers:

class AdminController < ApplicationController
  layout :admin

  def index
    render :dashboard

and it will nest nicely as expected.

The helper itself looks like:

module NestedLayoutsHelper
  # Wrap some content inside a layout
  def inside_layout(layout, &block)
    layout = layout.to_s
    layout = layout.include?('/') ? layout : "layouts/#{layout}"
    controller.render_to_body(:layout => layout, :text => capture { block.call(@_content_for[:layout]) })

There's a gist which puts it all together. I hope you find it useful too. Have fun!