Friday, June 20, 2008
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!
Subscribe to:
Post Comments (Atom)
3 comments:
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.
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 %>
Just wanted to say THANKS for your great solution - exactly what I needed.
Works perfect!
Post a Comment