# content\_for best practices

**URL:** <https://discuss.rubyonrails.org/t/content-for-best-practices/13426>\
**Category:** rubyonrails-talk\
**Created:** [May 24, 2007, 9:22pm UTC](https://discuss.rubyonrails.org/t/content-for-best-practices/13426 "2007-05-24T21:22:35Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Josh2](https://avatars.discourse-cdn.com/v4/letter/j/4491bb/32.png) [@Josh2](https://discuss.rubyonrails.org/u/Josh2)\
**Post date:** [May 24, 2007, 9:22pm UTC](https://discuss.rubyonrails.org/t/content-for-best-practices/13426/1 "2007-05-24T21:22:35Z")

</div>

recently i ready about using content\_for to add more dynamic control in my layouts.

wanting to keep DRY, i'm wondering what the best way is to use this is if i'm wanting to check specific areas for content. based on if there is or isn't, i would like to totally remove or add elements to the page.

while the example i am including works, it seems like this would probably be creating a lot more work than necessary...

\<% if(yield :sidebar) %\> &nbsp;&nbsp;\<div id="sidebar"\> &nbsp;&nbsp;&nbsp;&nbsp;\<%= yield :sidebar %\> &nbsp;&nbsp;\</div\> \<% end %\>

if this isn't a good way of doing it, please let me know why. and if there is an easy / clean way of doing it.

Thanks for the help

---

<div class="post-metadata">

**Author:** ![Jacob\_Atzen](https://avatars.discourse-cdn.com/v4/letter/j/73ab20/32.png) [@Jacob\_Atzen](https://discuss.rubyonrails.org/u/Jacob_Atzen)\
**Post date:** [May 24, 2007, 9:32pm UTC](https://discuss.rubyonrails.org/t/content-for-best-practices/13426/2 "2007-05-24T21:32:23Z")

</div>

Josh wrote:

> recently i ready about using content\_for to add more dynamic control in my layouts.
> 
> wanting to keep DRY, i'm wondering what the best way is to use this is if i'm wanting to check specific areas for content. based on if there is or isn't, i would like to totally remove or add elements to the page.
> 
> while the example i am including works, it seems like this would probably be creating a lot more work than necessary...
> 
> \<% if(yield :sidebar) %\> &nbsp;&nbsp;\<div id="sidebar"\> &nbsp;&nbsp;&nbsp;&nbsp;\<%= yield :sidebar %\> &nbsp;&nbsp;\</div\> \<% end %\>
> 
> if this isn't a good way of doing it, please let me know why. and if there is an easy / clean way of doing it.

Maybe you can find some inspiration from Err:

> **[Strut Your Structs — err.the\_blog](http://errtheblog.com/post/28)**
>
> Err the Blog: Ruby and Rails from the front.

---

<div class="post-metadata">

**Author:** ![Josh2](https://avatars.discourse-cdn.com/v4/letter/j/4491bb/32.png) [@Josh2](https://discuss.rubyonrails.org/u/Josh2)\
**Post date:** [May 24, 2007, 9:43pm UTC](https://discuss.rubyonrails.org/t/content-for-best-practices/13426/3 "2007-05-24T21:43:51Z")

</div>

Thanks for the reply Jacob. That blog post was actually one of the first links I came across.

I liked the idea for conditionals like this example:

&nbsp;&nbsp;\<%= (sidebar = yield :sidebar) ? sidebar : render(:partial =\> 'shared/sidebar') %\>

I guess I could do something like so:

view.rhtml: &nbsp;&nbsp;\<% content\_for :sidebar do %\> &nbsp;&nbsp;&nbsp;&nbsp;\<div id="sidebar"\> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;all of my content in here &nbsp;&nbsp;&nbsp;&nbsp;\</div\> \<% end %\>

and then in my layout: &nbsp;&nbsp;\<%= (sidebar = yield :sidebar) ? sidebar : '' %\>

but I'm still having to type that sidebar div everytime.

---

<div class="post-metadata">

**Author:** ![Jacob\_Atzen](https://avatars.discourse-cdn.com/v4/letter/j/73ab20/32.png) [@Jacob\_Atzen](https://discuss.rubyonrails.org/u/Jacob_Atzen)\
**Post date:** [May 24, 2007, 10:11pm UTC](https://discuss.rubyonrails.org/t/content-for-best-practices/13426/4 "2007-05-24T22:11:50Z")

</div>

Josh wrote:

> Thanks for the reply Jacob. That blog post was actually one of the first links I came across.
> 
> I liked the idea for conditionals like this example:
> 
> &nbsp;&nbsp;\<%= (sidebar = yield :sidebar) ? sidebar : render(:partial =\> 'shared/sidebar') %\>
> 
> I guess I could do something like so:
> 
> view.rhtml: &nbsp;&nbsp;\<% content\_for :sidebar do %\> &nbsp;&nbsp;&nbsp;&nbsp;\<div id="sidebar"\> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;all of my content in here &nbsp;&nbsp;&nbsp;&nbsp;\</div\> \<% end %\>
> 
> and then in my layout: &nbsp;&nbsp;\<%= (sidebar = yield :sidebar) ? sidebar : '' %\>
> 
> but I'm still having to type that sidebar div everytime.

If you have a default sidebar, then you could just put the div in the layout, right?

Or you could make it into a helper method, something like (untested):

def conditional\_element(name) &nbsp;&nbsp;&nbsp;element = yield(name.to\_sym) &nbsp;&nbsp;&nbsp;content\_tag(:div, element, :id =\> name.to\_s) if element end

I'm not sure exactly what the problem you're trying to solve is, so maybe I'm misunderstanding something 🙂

---

<div class="post-metadata">

**Author:** ![Josh2](https://avatars.discourse-cdn.com/v4/letter/j/4491bb/32.png) [@Josh2](https://discuss.rubyonrails.org/u/Josh2)\
**Post date:** [May 25, 2007, 12:20am UTC](https://discuss.rubyonrails.org/t/content-for-best-practices/13426/5 "2007-05-25T00:20:17Z")

</div>

> def conditional\_element(name) &nbsp;&nbsp;&nbsp;element = yield(name.to\_sym) &nbsp;&nbsp;&nbsp;content\_tag(:div, element, :id =\> name.to\_s) if element end

I might could get something like that to work. Basically I am just looking for a way to check and see if there is content for a specific area and adjust my markup, ids and classes accordingly.

Say I have a 3 column layout, and if there is no sidebar content, i want to be able to check and render a 2 column layout instead.

---

<div class="post-metadata">

**Author:** ![Jacob\_Atzen](https://avatars.discourse-cdn.com/v4/letter/j/73ab20/32.png) [@Jacob\_Atzen](https://discuss.rubyonrails.org/u/Jacob_Atzen)\
**Post date:** [May 25, 2007, 8:56am UTC](https://discuss.rubyonrails.org/t/content-for-best-practices/13426/6 "2007-05-25T08:56:38Z")

</div>

Josh wrote:

> > def conditional\_element(name) &nbsp;&nbsp;&nbsp;element = yield(name.to\_sym) &nbsp;&nbsp;&nbsp;content\_tag(:div, element, :id =\> name.to\_s) if element end
> 
> I might could get something like that to work. Basically I am just looking for a way to check and see if there is content for a specific area and adjust my markup, ids and classes accordingly.
> 
> Say I have a 3 column layout, and if there is no sidebar content, i want to be able to check and render a 2 column layout instead.

Sounds like you're trying to squeeze two templates into one with a resulting mess of conditional logic in the template. Perhaps it would be easier to just make two templates and then select the corresponding template from the controller dynamically? Or maybe I'm still not totally clear on what you're trying to achieve 😉

---

<div class="post-metadata">

**Author:** ![Josh2](https://avatars.discourse-cdn.com/v4/letter/j/4491bb/32.png) [@Josh2](https://discuss.rubyonrails.org/u/Josh2)\
**Post date:** [May 25, 2007, 12:40pm UTC](https://discuss.rubyonrails.org/t/content-for-best-practices/13426/7 "2007-05-25T12:40:09Z")

</div>

Yes, that is what i was trying to do. haha...

Maybe in this case, i should just stick with simple instead of dry and have two templates.

I did come up with something that worked for me for now though. This is what I have currently:

\<% left\_col = yield :left\_col -%\>

&nbsp;&nbsp;\<% if left\_col -%\> &nbsp;&nbsp;\<div id="left\_col"\> &nbsp;&nbsp;&nbsp;&nbsp;\<%= left\_col -%\> &nbsp;&nbsp;\</div\> &nbsp;&nbsp;\<% end -%\>

Thanks for your help though. I managed to learn a lot from the examples you provided for other pieces of my project.

---

<div class="post-metadata">

**Author:** ![Andrew\_Vit](https://avatars.discourse-cdn.com/v4/letter/a/a8b319/32.png) [@Andrew\_Vit](https://discuss.rubyonrails.org/u/Andrew_Vit)\
**Post date:** [May 25, 2007, 6:09pm UTC](https://discuss.rubyonrails.org/t/content-for-best-practices/13426/8 "2007-05-25T18:09:57Z")

</div>

# helper

module ApplicationHelper

&nbsp;&nbsp;def sidebar( args={}, html\_options={}, &block ) &nbsp;&nbsp;&nbsp;&nbsp;block\_to\_partial( 'shared/sidebar', args, html\_options, block ) &nbsp;&nbsp;end

&nbsp;&nbsp;def block\_to\_partial( template, args, html\_options, block ) &nbsp;&nbsp;&nbsp;&nbsp;template\_name = template.split('/').last &nbsp;&nbsp;&nbsp;&nbsp;args = { :title =\> args, :subtitle =\> nil } if args.is\_a?(String) && !args.empty? &nbsp;&nbsp;&nbsp;&nbsp;html\_options[:class] = if html\_options[:class].nil? &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;template\_name &nbsp;&nbsp;&nbsp;&nbsp;else &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;( html\_options[:class].split(' ') \<\< template\_name).join(' ') &nbsp;&nbsp;&nbsp;&nbsp;end &nbsp;&nbsp;&nbsp;&nbsp;vars = args.merge! :options =\> html\_options, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:@content\_for\_layout =\> capture(&block) &nbsp;&nbsp;&nbsp;&nbsp;concat render(:partial =\> template, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:locals =\> vars), block.binding &nbsp;&nbsp;end

end

# shared/\_sidebar.rhtml

\<% content\_tag 'div', options do -%\> \<%= content\_tag 'h3', title %\> \<%= content\_tag('h4', subtitle) unless subtitle.blank? %\> \<%= yield %\> \<% end %\>

# view

\<% sidebar 'Companies', :id =\> 'companies\_sidebar' do %\> \<ul\>...html lives here...\</ul\> \<% end %\>

# explanation

I use the nested\_layouts plugin and I find it invaluable... This helper pattern makes a perfect addition for when I need to pass things to other layers of my layout. You can use this in your case where you use content\_for.

I found block\_to\_partial somewhere on the interweb (forgot the source; if you want credit, speak up!). I customized it so that I can pass a String as the first parameter, which automatically becomes the title variable in the partial. Otherwise, I can pass a Hash for the vars needed in the partial that I don't want to consider "content":

sidebar :title=\>'Companies', :subtitle=\>'Mortgage Brokers' {...}

rather than yielding these as the content, it lets me render them as part of the partial, however I might want them commonly formatted in my partial temlate (DRYness!).

Based on this pattern, I've defined other helpers that accomplish similar tasks. I used title as the only convention for all partials so I could pass a string for it. This might not be necessary for your case, and if you need to define other things instead, you can just pass a hash when you call it.

It works well for all my needs. Improvements? Suggestions?

--Andrew Vit
