If you’ve ever taken the time to factor out the various commonalities that often exist in your Rails views into partials, you’ve probably noticed that there are still opportunities for DRYing up those partials. Well now you have a tool in your toolbox to help partials become first class citizens in the view-world: partial layouts. It’s as easy as adding a :layout option to your render call:
1 2 3 4 5 6 7 8 9 10 |
<!-- in posts/show.html.erb --> <%= render :partial => 'header', :layout => 'boxed', :locals => {:post => @post} %> <!-- in posts/_boxed.html.erb --> <div class='box'> <div id='post_header_<%= post.id %>'><%= yield %></div> </div> <!-- in posts/_header.html.erb --> <%= post.title %> published on <%= post.published_at %> |
Notice that the partial layout boxed still uses the partial naming convention of an _ prefix and that it exists in the same directory as the calling file (i.e. it doesn’t have it’s own layouts directory like the other master layouts do). Also notices that any locals passed into the partial render are also made available to the partial layout (post in this case.) You include the content of the partial into the layout by calling yield, as you do in the master templates.
So with the above setup, the rendering of posts/show.html.erb will result in this:
1 2 3 |
<div class='box'> <div id='post_header_1'>Post Title published on August 3rd, 2007</div> </div> |
You also have the ability to render a block of code within a partial layout if you want the consistency a layout provides but don’t necessarily have the need to break off the content into its own partial:
1 2 3 4 |
<!-- in posts/show.html.erb --> <% render(:layout => 'boxed', :locals => {:post => @post}) do %> <%= post.title %> published on <%= post.published_at %> <% end %> |
DRY away.
tags: ruby, rubyonrails

Nice, I could have really used this a few months ago. My solution was ugly but still managed to follow DRY. I like.
Finaly!! This is something I really miss in rails.
Very neat. Nice edition.
When will they come up with solution to wrap anything in a layout like nested-layouts plugin allow to do ?
Rails improvements seem to make code harder and harder to read with every commit. At this point, if I’m not repeating myself, it’s because I somehow managed to cram the entire tree of render() arguments and their calling conventions into my head without going nuts. I thought there was a policy against changes that would complicate things like this? What happened to new features being added as plugins?
This works really well until you try to render a partial with layout in your site layout, the @content_for_layout gets overwritten by the contents of the rendered partial!
For an explanation see http://cumu.li/2007/8/8/first-patch-submitted-to-rails and associated patch at http://dev.rubyonrails.org/ticket/9209
Sorry, updated URL describing patch to http://cumu.li/2007/8/8/errors-when-rendering-a-partial-with-a-layout
This seems like a great idea, however if used with a collection, would it not be better to only render the layout once and the partial x number of times?
At the minute both are rendered x number of times
Great feature, this is much cleaner, currently I did a hack through helper method with a block and concat.