# Sub-layouts

**URL:** <https://www.ruby-forum.com/t/sub-layouts/149962>\
**Category:** Rails\
**Created:** [October 1, 2008, 7:19pm UTC](https://www.ruby-forum.com/t/sub-layouts/149962 "2008-10-01T19:19:46Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Garrett\_B](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/4da419/32.png) [@Garrett\_B](https://www.ruby-forum.com/u/Garrett_B)\
**Post date:** [October 1, 2008, 7:19pm UTC](https://www.ruby-forum.com/t/sub-layouts/149962/1 "2008-10-01T19:19:46Z")

</div>

I have a nice layout for my app, but for some actions I want to use a  
shared sub layout. Anyone have ideas what the best practice would  
be? I have a method that works, but I am not sure if it is the ‘rails  
way’ of doing things, anyone care to critique it? I have tried the  
following…

1. making my action template call  
render :partial, :collection, :layout. The good new here is that it  
wraps the layout around the whole collection (not around each item in  
the collection) and doesn’t blow away my main layout. The bad news is  
the sub-layout and collection are repeated as many times as there are  
items in the collection. This seems like a rails bug. The layout  
should be applied once around the whole collection, or once for each  
item in the collection, not both.

2. applying a layout to the render :action in the controller. This  
blows away my main layout. This is because i am rendering a template,  
not a partial, right?

3. using content\_for to define a sub-layout. this works, but I feel  
like there should be an easier way. i am also not sure yet what would  
happen when i don’t want a sub-layout. I guess I could make a  
\_no\_sub\_layout.html.erb that just yields, or put the content all  
inside of the content\_for block…I have a few other ideas too. One  
possible benefit is that I think you could keep nesting sub-layouts  
pretty easily if you wanted. Here is a simplified version of this  
solution.

layout.html.erb

head stuff some stuff \<%= yield :sublayout %\> some stuff

index.html.erb  
\<% content\_for :sublayout do -%\>  
\<%= render :partial =\>“sublayout” %\>  
\<% end -%\>

\<% for item in @collection do -%\>  
\<%= render :partial =\> “item” -%\>  
\<% end -%\>

\_sublayout.html.erb  
some stuff  
\<%= yield %\>  
some stuff

\_item.html.erb  
\<%= h item.name %\>

---

<div class="post-metadata">

**Author:** ![Garrett\_B](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/4da419/32.png) [@Garrett\_B](https://www.ruby-forum.com/u/Garrett_B)\
**Post date:** [October 1, 2008, 7:33pm UTC](https://www.ruby-forum.com/t/sub-layouts/149962/2 "2008-10-01T19:33:19Z")

</div>

I don’t know why I though the third method worked…anyway, a little  
tweaking gives me this, which does work. Instead of the content\_for I  
pass a rendered collection into \_sublayout as a local variable named  
content.

1. 

layout.html.erb

 head stuff some stuff \<%= yield %\> some stuff 

index.html.erb  
\<%= render :partial =\>“sublayout”, :locals =\> { :content =\>  
(render :partial =\> “item”, :collection =\> @items) } -%\>

\_sublayout.html.erb  
some stuff  
\<%= content %\>  
some stuff

\_item.html.erb  
\<%= h item.name %\>

On Oct 1, 1:04 pm, Garrett B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

---

<div class="post-metadata">

**Author:** ![Garrett\_B](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/4da419/32.png) [@Garrett\_B](https://www.ruby-forum.com/u/Garrett_B)\
**Post date:** [October 1, 2008, 11:46pm UTC](https://www.ruby-forum.com/t/sub-layouts/149962/3 "2008-10-01T23:46:37Z")

</div>

Have you checked out Ryan B. railscasts - you might try

> **[\#7 All About Layouts - RailsCasts](http://railscasts.com/episodes/7-all-about-layouts)**
>
> Short Ruby on Rails screencasts containing tips, tricks and tutorials. Great for both novice and experienced web developers.

He also has some other ones on layouts. His railscasts are great  
Owen

On Oct 1, 10:32 am, Garrett B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

---

<div class="post-metadata">

**Author:** ![Garrett\_B](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/4da419/32.png) [@Garrett\_B](https://www.ruby-forum.com/u/Garrett_B)\
**Post date:** [October 2, 2008, 3:20am UTC](https://www.ruby-forum.com/t/sub-layouts/149962/4 "2008-10-02T03:20:07Z")

</div>

I have seen his website before, but the videos don’t play on my  
computer. Recently my computer just started having some problems with  
video files and I haven’t taken the time to figure out the problem.  
Regardless I think I have pieced together something decent, kind of a  
cross between methods 3 and 4. The only thing that kinda still bugs  
me is needing a no\_sublayout.html.erb. I have been trying in vain to  
find a why to get the the main\_layout to choose between  
yield :sublayout or yield :layout. It looks like this…

views/layouts/main\_layout.html.erb  
some html  
\<%= yield :sublayout %\>  
some html

views/items/index.html.erb  
render :partial =\> “item”, :collection =\> @items

views/items/\_item.html.erb  
\<%= h item.name $\>

views/layouts/sublayout.html.erb  
\<% content\_for sublayout do -%\>  
some html  
\<%= yield %\>  
some html  
\<% end -%\>  
render :file=\>“layouts/main\_layout.html.erb”

views/layouts/no\_sublayout.html.erb  
\<% content\_for sublayout do -%\>  
\<%= yield %\>  
\<% end -%\>  
render :file=\>“layouts/main\_layout.html.erb”

controllers/items\_controller.rb  
layout :choose\_layout  
normal controller stuff  
private  
def choose\_layout  
if action\_name == “index” “sublayout”  
else “no\_sublayout”  
end  
end

now on to the next iteration…i am using this with nested resources  
and would like to keep nesting more sublayouts, hahaha.  
G
