Wednesday, April 16, 2008

DRY up your views with nested partials

NOTE: I got a couple of comments letting me know that the proper way to do this is to use a layout with your partial. Please see this post for instructions. Since making this post, I've been told the partial nesting is generally a bad idea, so use at your own risk.




Got a good one for you today that should help clean up your views and DRY things out. How many times, when building a website, do you use the same code over and over again to build this cool looking window that is re-used over and over?


 
<div id="window-top"></div>
<div id="window">
<%= render :partial => 'mypartial' %>
</div>
<div id="window-bottom"></div>

<div id="window-top"></div>
<div id="window">
<%= render :partial => 'myotherpartial' %>
</div>
<div id="window-bottom"></div>

Well, you can use nested partials to achieve the same effect and re-use your window code. First, lets create a partial called '_lorem.html.erb':



<p>"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat
non proident, sunt in culpa qui officia deserunt mollit anim id est
laborum." </p>

And another called '_blah.html.erb':



<p>blah blah blah blah blah blah blah blah blah blah blah blah blah
blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah
blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah
blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah
blah blah blah </p>


Alright! Now, make one last partial, '_window.html.erb'. This is where you put the code for the cool window you just made.
Inside of it, you want to render a partial, and pass in the variable 'name':



<div id="window-container">
<div id="window-top-left"></div><div id="window-top">Window Title</div>
<div id="window-top-right"></div>
<div id="window">
<%= render :partial => name %>
</div>
<div id="window-bottom-left"></div><div id="window-bottom">
</div><div id="window-bottom-right"></div>
</div>

And now, when you want to render a partial that is inside your window, all you need to do is render the 'window' partial, and as a local
variable named 'name', pass in the name of the partial you want rendered inside of it:



<h1>Test of nested partials</h1>

<%= render :partial => 'window', :locals => {:name => 'lorem' } %>

<%= render :partial => 'window', :locals => {:name => 'blah' } %>


And thats it! Enjoy DRYing up your views with nested partials. Later

-Ralph

3 comments:

Mr eel said...

Nested partials can be a bit of a killer for performance. As always YMMV, but worth keeping in mind.

Jellybob said...

You can also use the :layout option when rendering a partial, which works the same as when rendering full actions, and is designed for exactly this sort of situation.

rledge21 said...

Thanks for the input guys, I'll update the post with that info Monday.