Nested layouts? whole site layout + controller layout?

Hi,

I was hoping to use one overall layout at the application.rb level
(layout “site_layout”) plus have another layout within this at the
controller level, however I can’t seem to get this to work. If I do put
in a specific controller layout it seems to override the application.rb
level one.

So is it not possible therefore to have a nested layout in rails?

If no how are people handling an overall site layout (e.g. header,
footer) and then controller specific layouts which might say have a
specific layout for the navigation (say on left of content area) and
content area?

Tks

PS. I had the following overall layout in mind:

-----------------HEADER------------------

---------MENU ITEMS, TOP LEVEL ----------

–MENU ITEM – - CONTENT AREA-----
–SPECIFIC – -------------------
–NAVIGATION-- -------------------

  • controller-- -------------------
  • specific – -------------------

----------------------FOOTER ------------

Tks - I’ve got content_for working ok. I can use a layout for the
overall
header/footer and nav/content area layout. In this layout file then:
a) In the Navigation area I use: <%= yield :navigation_content %> and
b) In the content area I use: <%= @content_for_layout %>

Within each of a controller view I use <%= render :partial =>
‘contact_navigation’ %> as I have to put this in each of the views for a
given controller. This way I can put the actual controller specific
navigation in a file such as _contact_navigation.rhtml.

The only problem here is that one has to put the an entry such as <%=
render
:partial => ‘contact_navigation’ %> in EACH of the views in that
controller
area. It would be beter to have this automatically occur, which I
guess is
getting back to the concept of having a layout at the controller level
too.
So a layout (controller specific) within a layout (the overall site
layout).

Is there a way to achieve this? (given that layouts within layouts
don’t
seem to work)

Greg

On Aug 26, 2006, at 4:12 PM, Greg H. wrote:

I was hoping to use one overall layout at the application.rb level
(layout “site_layout”) plus have another layout within this at the
controller level, however I can’t seem to get this to work. If I
do put
in a specific controller layout it seems to override the
application.rb
level one.

Have a look at content_for.

Rails API: http://rails.rubyonrails.org/classes/ActionView/Helpers/
CaptureHelper.html

Example from the layout’s perspective: http://thoughts.pjhyett.com/
day/46#thought-113


Chris W.

On Aug 27, 2006, at 3:21 AM, Greg H wrote:

b) In the content area I use: <%= @content_for_layout %>

You can just use ‘yield’ with no arguments. No need for
@content_for_layout.

Is there a way to achieve this? (given that layouts within layouts
don’t seem to work)

<%= render :partial => (controller.controller_name + ‘/
contact_navigation’) %> ?

Consider using render :file, as well, if content_for isn’t doing what
you want.


Chris W.

Chris - I guess what I’m after is a way to handle the navigation pane
without having to put knowledge of this (or any additional lines) into
each
of controllers view files, i.e. don’t want to have to put something into
list.rhtml, new.rhtml, edit.rhtml, show.rhtml each time (i.e. number of
controllers x about 4-5).

Seeing I’m already using the rails layout concept for my overall site
specific header/footer layout, to do what I want I guess I need a way to
inject a “layout” like concept in the controller itself, for example in
contact.rb (i.e. I guess I’m trying not to have to modify the outcome of
the
rails scaffold generated views etc). Would any of the ideas you were
suggested be able to do this?

PS - Just come across this (
http://gridpt1.fe.up.pt/mlopes/blog/index.php/2006/08/12/nested-layouts-in-ruby-on-rails/).
I’ll have to digest this as the intro at least seems to be acknowledging
the
problem and desire to do what I was asking for

That looks like a good technique for what you want to do. I just tried
it on my app but i get an undefined method error…
ActionView::TemplateError (undefined method `inside_layout’ for
#<#Class:0x32205cc:0x32205a4>) on line #1 of
app/views/layouts/store.rhtml:

Weird. The method is definitely defined and required in the
environment…

Sean

Perhaps this should be incorporated into rails itself. What do you
think?
From my perspective it should.

Got the layout within layout concept working (i.e.
http://gridpt1.fe.up.pt/mlopes/blog/index.php/2006/08/12/nested-layouts-in-ruby-on-rails/)

I’ve realised what I also really want to to be able to:

a) define the DIV based layout in the overall rails layout (e.g. defines
where the left side navigation is, as well as header/footer/content)

b) populate the navigation area on a controller specific basis, but
without
the individual view pages having to have anything to do with this.

I think I could do this using “content_for” (
ActionView::Helpers::CaptureHelper)
however I really need to be able to set the instance variable within the
controller. I’ve tried this but no luck yet (still new to ruby).

Anyone suggest where I’m going wrong here?

contacts_controller.rb

class ContactsController < ApplicationController
include ActionView::Helpers::CaptureHelper

@navigation_content = capture do


link_to ‘New contact(asdfasdf)’, :action => ‘new’”
end

==> Gives the following error = "NoMethodError - undefined method
`capture’
for ContactsController:Class "

Thanks

Oops, that was just my mistake… I had omitted the last couple of
lines to be included in environment.rb… The method works perfectly
now and has saved me from rendering the same partial about 20
times…

Sean

Hi,

One option you could employ as an alternative to inserting render
partial lines in all of your views, is to add the following lines to one
of your controllers.
(this is a bit dirty but it works)

before_filter :side_bar

def side_bar
assigns[:side] = response.template.render(:partial => ‘side_bar’)
response.template.instance_variable_set(:@assigns_added, nil)
end

And then in your ‘layout’

<% if @side -%>

<%= @side %>

<%= yield %>

<% else -%>
<%= yield %>
<% end -%>

Yes this violates both encapsulation and MVC… but if you’re
comfortable doing that, this can save you from having to add lines like
this to your views:

<% @side = capture do -%>
<%= render :partial => ‘side_bar’ %>
<% end -%>