Creating a Layout for Your Header and Footer

Problem

You want to create a header and footer for every page on your web application. Certain pages should have special headers and footers, and you may want to dynamically determine which header and footer to use for a given request.

Solution

Many web applications let you define header and footer files, and automatically include those files at the top and bottom of every page. Rails inverts this pattern. A single file called contains both the header and footer, and the contents of each particular page are inserted into this file.

To apply a layout to every page in your web application, create a file called app/views/layouts/application.rhtml. It should look something like this:

	
	 
	 My Website
	 
	 
	 <%= @content_for_layout %>
	 
	

The key piece of information in any layout file is the directive <%= content_for_layout %>. This is replaced by the content of each individual page.

You can make customized layouts for each controller independently by creating files in the app/views/layouts folder. For example, app/views/layouts/status.rhtml is the layout for the status controller, StatusController. The layout file for PriceController would be price.rhtml.

Customized layouts override the site-wide layout; they don add to it.

Discussion

Just like your main view templates, your layout templates have access to all the instance variables set by the action. Anything you can do in a view, you can do in a layout template. This means you can do things like set the page title dynamically in the action, and then use it in the layout:

	class StatusController < ActionController:Base
	 def index
	 @title = "System Status"
	 end
	end

Now the application.rhtml file can access @title like this:

	
	 
	 My Website - <%= @title %>
	 
	 
	 <%= @content_for_ 
layout %>
	 
	

application.rhtml doesn just happen to be the default layout template for a Rails applications controllers. It happens this way because every controller inherits from ApplicationController. By default, a layouts name is derived from the name of the controllers class. So ApplicationController turns into application.rhtml. If you had a controller named MyFunkyController, the default filename for the layout would be app/views/layouts/my_funky.rhtml. If that file didn exist, Rails would look for a layout corresponding to the superclass of MyFunkyController, and find it in app/views/layouts/application.rhtml.

To change a controllers layout file, call its layout method:

	class FooController < ActionController:Base
	 # Force the layout for /foo to be app/views/layouts/bar.rhtml,
	 # not app/view/layouts/foo.rhtml.
	 layout ar
	end

If you e using the render method in one of your actions (see Recipe 15.5), you can pass in a :layout argument to render and give that action a different layout from the rest of the controller. In this example, most actions of the FooController use bar.rhtml for their layout, but the count action uses count.rhtml:

	class FooController < ActionController:Base
	 layout ar

	 def count
	 @data = [1,2,3]
	 render :layout => count
	 end
	end

You can even have an action without a layout. This code gives all of FooControllers actions a layout of bar.html, except for the count action, which has no layout at all: its responsible for all of its own HTML.

	class FooController < ActionController:Base
	 layout ar, :except => count
	end

If you need to calculate the layout file dynamically, pass a method symbol into the layout method. This tells layout to call a method on each request; the return value of this method defines the layout file. The method can call action_name to determine the action name of the current request.

	class FooController < ActionController:Base
	 layout :figure_out_layout

	 private

	 def figure_out_layout
	 if action_name =~ /pretty/
	 pretty # use pretty.rhtml for the layout
	 else
	  
standard # use standard.rhtml
	 end
	 end
	end

Finally, layout accepts a lambda function as an argument. This lets you dynamically decide on a layout with less code:

	class FooController < ActionController:Base
	 layout lambda { |controller| controller.logged_in? ? user : guest }
	end

Its freeing for both the programmer and the designer to use a layout file instead of separate headers and footers: its easier to see the whole picture. But if you need to use explicit headers and footers, you can. Create files called app/views/layouts/_ header.rhtml and app/views/layouts/_footer.rhtml. The underscores indicate that they are "partials" (see Recipe 15.14). To use them, set your actions up to use no layout at all, and write the following code in your view files:

	<%= render :partial => layouts/header %>
	… your views content goes here …
	<%= render :partial => layouts/footer %>

See Also

  • Recipe 15.5, "Displaying Templates with Render"
  • Recipe 15.14, "Refactoring the View into Partial Snippets of Views"


Strings

Numbers

Date and Time

Arrays

Hashes

Files and Directories

Code Blocks and Iteration

Objects and Classes8

Modules and Namespaces

Reflection and Metaprogramming

XML and HTML

Graphics and Other File Formats

Databases and Persistence

Internet Services

Web Development Ruby on Rails

Web Services and Distributed Programming

Testing, Debugging, Optimizing, and Documenting

Packaging and Distributing Software

Automating Tasks with Rake

Multitasking and Multithreading

User Interface

Extending Ruby with Other Languages

System Administration



Ruby Cookbook
Ruby Cookbook (Cookbooks (OReilly))
ISBN: 0596523696
EAN: 2147483647
Year: N/A
Pages: 399

Similar book on Amazon

Flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net