Nested Layouts in Rails


I was wondering how to keep the layouts in my rails application code DRY – I was close to the point of kicking myself for having to make changes to all my layouts whenever something standard changed – so i researched online and found the above diagram by Matt McCray in his blog.

I used Matt’s method for nesting layouts, but instead of defining a method called sub_layout in my controllers, I called a pre-defined rails controller method:

< % render :partial => “layouts/#{controller.controller_name}” %>

and defined a partial layout named after every controller I had, which had different settings for their own views. Rails has a local variable called ‘controller’ you can use to access its controller’s name and even the action used for the current view. So using this, I don’t have to define additional methods in my controllers, nor use any plugins.

kudos to Matt for coming up with this in the first place. Thanks!

3 Responses to “Nested Layouts in Rails”

  1. Weyus August 23, 2008 at 6:16 am #

    You can take this a step further.

    If you want to mix and match your "layouts" (which are really just partials, let's face it) across arbitrary controller/action pairs, you can just define a special variable, say @inner_layout.

    And then in each action that you want to use the inner layout, you just define it.

    So in your application.html.erb:

    <%= @inner_layout ? render(:partial => "layouts/#{@inner_layout}") : yield %>

    If there's an inner "layout" (partial) then render it (assuming that it will yield), and if there isn't one, just go ahead and yield.

    And then in the appropriate action(s):

    @inner_layout = 'some_inner_layout_filename'.

    Although the variable thing is a bit of a drag, you could take this as far as you want.

  2. Steven Parkes September 12, 2008 at 4:17 am #

    I didn't need a new nested layout for every controller, just a few. Well, one to start. Simply wrapping the render :partial with a block and catching the MissingTemplate, where you drop back to yield, (seems to) work great:

    <%= begin; render :partial => "layouts/#{controller.controller_name}"; rescue ActionView::MissingTemplate; yield; end %>

  3. Vered October 7, 2008 at 6:27 pm #

    Just wanted to say THANKS for your great solution – exactly what I needed.
    Works perfect!

Leave a Reply