Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HAML and Nested Layouts

Essentially what I want to do is have a root application.haml that contains the core css and js then the site layout goes something like

  • application.haml
    • marketing.haml(s) with their own css's and markups
    • userbackend.haml(s) with their own css's and markups
    • siteadministrators.haml(s) with their own css's and markups

So I tried doing this by adding a sub_layout to my controllers so for instance my home controller which is a marketing sections gets:

def sub_layout
    "marketing"
  end

controllers for the actualy application that the users use

def sub_layout
   "userapplication"
end

def sub_layout
   "siteadministrators"
end

then in the application.haml I call = render(:parital => "layouts/#{controller.sub_layout}")

this returns "undefined method `formats' for nil:NilClass"

Like many on here I'm very new to rails and haml especially though I do have experience with .NET MVC and the Spark View engine

any thoughts on what this haml looks like?

like image 836
maehue Avatar asked Dec 07 '10 05:12

maehue


2 Answers

As you suspected, there is a standard and much, much better way of doing this. Your application.haml:

!!! XML
!!!
%html
  %head
    %title Title
    = stylesheet_link_tag 'global'
    = yield :styles
  %body
    #content
      = yield
    = yield :scripts

And then your marketing.haml:

- content_for :styles do
  = stylesheet_link_tag 'marketing'

- content_for :scripts do
  = javascript_include_tag 'marketing'

%h1 It's Marketing time!

Anything in the 'content_for :styles' block gets executed in the context of it's respective yield in the layout. You don't need to have a content_for for every yield, if you have multiple, the results get concatenated.

Enjoy!

like image 163
gunn Avatar answered Oct 18 '22 21:10

gunn


Try this:

= render :file => "layouts/#{controller.sub_layout}"

Calling a method on the controller is problematic in that it potentially exposes your method as an action. Since you're just returning a string, you could do this (e.g.):

class HomesController < ApplicationController
  @@sub_layout = "marketing"
  cattr_reader :sub_layout

A better option is probably to abstract this into a helper method where you can lookup the value with the controller class and return the layout file name. That would keep the controllers cleaner.

like image 42
zetetic Avatar answered Oct 18 '22 21:10

zetetic