Permalink
Browse files

Layout & Rendering Guide

  • Loading branch information...
1 parent 2c04538 commit a79942542eb022812ebd6cf2f857d8ad5f6e1f07 @ffmike ffmike committed Sep 28, 2008
Showing with 342 additions and 5 deletions.
  1. +2 −1 railties/Rakefile
  2. +330 −4 railties/doc/guides/actionview/layouts_and_rendering.txt
  3. +10 −0 railties/doc/guides/index.txt
View
@@ -288,7 +288,8 @@ guides = [
{ 'activerecord' => 'finders' },
{ 'debugging' => 'debugging_rails_applications' },
{ 'caching' => 'caching_with_rails' },
- { 'benchmarking_and_profiling' => 'preamble' }
+ { 'benchmarking_and_profiling' => 'preamble' },
+ { 'actionview' => 'layouts_and_rendering' }
]
guides_html_files = [] # autogenerated from the 'guides' variable.
@@ -1,5 +1,5 @@
Layouts and Rendering in Rails
-=====================================
+==============================
This guide covers the basic layout features of Action Controller and Action View. By referring to this guide, you will be able to:
@@ -332,21 +332,347 @@ head :created, :location => photo_path(@photo)
== Structuring Layouts
-=== Include Statements
+When Rails renders a view as a response, it does so by combining the view with the current layout. To find the current layout, Rails first looks for a file in +app/views/layouts+ with the same base name as the controller. For example, rendering actions from the +PhotosController+ class will use +/app/views/layouts/photos.html.erb+. If there is no such controller-specific layout, Rails will use +/app/views/layouts/application.html.erb+. You can also specify a particular layout by using the +:layout+ option to +render+.
+
+Within a layout, you have access to three tools for combining different bits of output to form the overall response:
+
+* Asset tags
+* +yield+ and +content_for+
+* Partials
+
+I'll discuss each of these in turn.
+
+=== Asset Tags
+
+Asset tags provide methods for generating HTML that links views to assets like images, javascript, stylesheets, and feeds. There are four types of include tag:
+
+* auto_discovery_link_tag
+* javascript_include_tag
+* stylesheet_link_tag
+* image_tag
+
+You can use these tags in layouts or other views, although the tags other than +image_tag+ are most commonly used in the +<head>+ section of a layout.
+
+WARNING: The asset tags do _not_ verify the existence of the assets at the specified locations; they simply assume that you know what you're doing and generate the link.
+
+==== Linking to Feeds with +auto_discovery_link_tag+
+
+The +auto_discovery_link_tag helper builds HTML that most browsers and newsreaders can use to detect the presences of RSS or ATOM feeds. It takes the type of the link (+:rss+ or +:atom+), a hash of options that are passed through to url_for, and a hash of options for the tag:
+
+[source, ruby]
+-------------------------------------------------------
+<%= auto_discovery_link_tag(:rss, {:action => "feed"}, {:title => "RSS Feed"}) %>
+-------------------------------------------------------
+
+There are three tag options available for +auto_discovery_link_tag+:
+
+* +:rel+ specifies the +rel+ value in the link (defaults to "alternate")
+* +:type+ specifies an explicit MIME type. Rails will generate an appropriate MIME type automatically
+* +:title+ specifies the title of the link
+
+==== Linking to Javascript Files with +javascript_include_tag+
+
+The +javascript_include_tag+ helper returns an HTML +<script>+ tag for each source provided. Rails looks in +public/javascripts+ for these files by default, but you can specify a full path relative to the document root, or a URL, if you prefer. For example, to include +public/javascripts/main.js+:
+
+[source, ruby]
+-------------------------------------------------------
+<%= javascript_include_tag "main" %>
+-------------------------------------------------------
+
+To include +public/javascripts/main.js+ and +public/javascripts/columns.js+:
+
+[source, ruby]
+-------------------------------------------------------
+<%= javascript_include_tag "main", "columns" %>
+-------------------------------------------------------
+
+To include +public/javascripts/main.js+ and +public/photos/columns.js+:
+
+[source, ruby]
+-------------------------------------------------------
+<%= javascript_include_tag "main", "/photos/columns" %>
+-------------------------------------------------------
+
+To include +http://example.com/main.js+:
+
+[source, ruby]
+-------------------------------------------------------
+<%= javascript_include_tag "http://example.com/main.js" %>
+-------------------------------------------------------
+
+The +defaults+ option loads the Prototype and Scriptaculous libraries:
+
+[source, ruby]
+-------------------------------------------------------
+<%= javascript_include_tag :defaults %>
+-------------------------------------------------------
+
+The +all+ option loads every javascript file in +public/javascripts+, starting with the Prototype and Scriptaculous libraries:
+
+[source, ruby]
+-------------------------------------------------------
+<%= javascript_include_tag :all %>
+-------------------------------------------------------
+
+You can supply the +:recursive+ option to load files in subfolders of +public/javascripts+ as well:
+
+[source, ruby]
+-------------------------------------------------------
+<%= javascript_include_tag :all, :recursive %>
+-------------------------------------------------------
+
+If you're loading multiple javascript files, you can create a better user experience by combining multiple files into a single download. To make this happen in production, specify +:cache => true+ in your +javascript_include_tag+:
+
+[source, ruby]
+-------------------------------------------------------
+<%= javascript_include_tag "main", "columns", :cache => true %>
+-------------------------------------------------------
+
+==== Linking to CSS Files with +stylesheet_link_tag+
+
+The +stylesheet_link_tag+ helper returns an HTML +<link>+ tag for each source provided. Rails looks in +public/stylesheets+ for these files by default, but you can specify a full path relative to the document root, or a URL, if you prefer. For example, to include +public/stylesheets/main.cs+:
+
+[source, ruby]
+-------------------------------------------------------
+<%= stylesheet_link_tag "main" %>
+-------------------------------------------------------
+
+To include +public/stylesheets/main.css+ and +public/stylesheets/columns.css+:
+
+[source, ruby]
+-------------------------------------------------------
+<%= stylesheet_link_tag "main", "columns" %>
+-------------------------------------------------------
+
+To include +public/stylesheets/main.css+ and +public/photos/columns.css+:
+
+[source, ruby]
+-------------------------------------------------------
+<%= stylesheet_link_tag "main", "/photos/columns" %>
+-------------------------------------------------------
+
+To include +http://example.com/main.cs+:
+
+[source, ruby]
+-------------------------------------------------------
+<%= stylesheet_link_tag "http://example.com/main.cs" %>
+-------------------------------------------------------
+
+By default, +stylesheet_link_tag+ creates links with +media="screen" rel="stylesheet" type="text/css"+. You can override any of these defaults by specifying an appropriate option (:media, :rel, or :type):
+
+[source, ruby]
+-------------------------------------------------------
+<%= stylesheet_link_tag "main_print", media => "print" %>
+-------------------------------------------------------
+
+The +all+ option links every CSS file in +public/stylesheets+:
+
+[source, ruby]
+-------------------------------------------------------
+<%= stylesheet_link_tag :all %>
+-------------------------------------------------------
+
+You can supply the +:recursive+ option to link files in subfolders of +public/stylesheets+ as well:
+
+[source, ruby]
+-------------------------------------------------------
+<%= stylesheet_link_tag :all, :recursive %>
+-------------------------------------------------------
+
+If you're loading multiple CSS files, you can create a better user experience by combining multiple files into a single download. To make this happen in production, specify +:cache => true+ in your +stylesheet_link_tag+:
+
+[source, ruby]
+-------------------------------------------------------
+<%= stylesheet_link_tag "main", "columns", :cache => true %>
+-------------------------------------------------------
+
+==== Linking to Images with +image_tag+
+
+The +image_tag+ helper builds an HTML +<image>+ tag to the specified file. By default, files are loaded from +public/images+. If you don't specify an extension, .png is assumed by default:
+
+[source, ruby]
+-------------------------------------------------------
+<%= image_tag "header" %>
+-------------------------------------------------------
+
+You can supply a path to the image if you like:
+
+[source, ruby]
+-------------------------------------------------------
+<%= image_tag "icons/delete.gif" %>
+-------------------------------------------------------
+
+You can supply a hash of additional HTML options:
+
+[source, ruby]
+-------------------------------------------------------
+<%= image_tag "icons/delete.gif", :height => 45 %>
+-------------------------------------------------------
+
+There are also three special options you can use with +image_tag+:
+
+* +:alt+ specifies the alt text for the image (which defaults to the file name of the file, capitalized and with no extension)
+* +:size+ specifies both width and height, in the format "{width}x{height}" (for example, "150x125")
+* +:mouseover+ sets an alternate image to be used when the onmouseover event is fired.
=== Understanding +yield+
+Within the context of a layout, +yield+ identifies a section where content from the view should be inserted. The simplest way to use this is to have a single +yield+, into which the entire contents of the view currently being rendered is inserted:
+
+[source, html]
+-------------------------------------------------------
+<html>
+ <head>
+ </head>
+ <body>
+ <%= yield %>
+ <hbody>
+</html>
+-------------------------------------------------------
+
+You can also create a layout with multiple yielding regions:
+
+[source, html]
+-------------------------------------------------------
+<html>
+ <head>
+ <%= yield :head %>
+ </head>
+ <body>
+ <%= yield %>
+ <hbody>
+</html>
+-------------------------------------------------------
+
+The main body of the view will always render into the unnamed +yield+. To render content into a named +yield+, you use the +content_for+ method.
+
=== Using +content_for+
+The +content_for+ method allows you to insert content into a +yield+ block in your layout. You only use +content_for+ to insert content in named yields. For example, this view would work with the layout that you just saw:
+
+[source, html]
+-------------------------------------------------------
+<% content_for :head do %>
+ <title>A simple page</title>
+<% end %>
+
+<p>Hello, Rails!</p>
+-------------------------------------------------------
+
+The result of rendering this page into the supplied layout would be this HTML:
+
+[source, html]
+-------------------------------------------------------
+<html>
+ <head>
+ <title>A simple page</title>
+ </head>
+ <body>
+ <p>Hello, Rails!</p>
+ <hbody>
+</html>
+-------------------------------------------------------
+
+The +content_for+ method is very helpful when your layout contains distinct regions such as sidebars and footers that should get their own blocks of content inserted. It's also useful for inserting tags that load page-specific javascript or css files into the header of an otherwise-generic layout.
+
=== Using Partials
-< toc tbd >
+Partial templates - usually just called "partials" - are another device for breaking apart the rendering process into more manageable chunks. With a partial, you can move the code for rendering a particular piece of a response to its own file.
+
+==== Naming Partials
+
+To render a partial as part of a view, you use the +render+ method within the view, and include the +:partial+ option:
+
+[source, ruby]
+-------------------------------------------------------
+<%= render :partial => "menu" %>
+-------------------------------------------------------
+
+This will render a file named +_menu.html.erb+ at that point within the view being rendered. Note the leading underscore character: partials are named with a leading underscore to distinguish them from regular views, even though they are referred to without the underscore. This holds true even when you're pulling in a partial from another folder:
+
+[source, ruby]
+-------------------------------------------------------
+<%= render :partial => "shared/menu" %>
+-------------------------------------------------------
+
+That code will pull in the partial from +app/views/shared/_menu.html.erb+.
+
+==== Using Partials to Simplify Views
+
+One way to use partials is to treat them as the equivalent of subroutines: as a way to move details out of a view so that you can grasp what's going on more easily. For example, you might have a view that looked like this:
+
+[source, html]
+-------------------------------------------------------
+<%= render :partial => "shared/ad_banner" %>
+
+<h1>Products</h1>
+
+<p>Here are a few of our fine products:</p>
+...
+
+<%= render :partial => "shared/footer" %>
+-------------------------------------------------------
+
+Here, the +_ad_banner.html.erb+ and +_footer.html.erb+ partials could contain content that is shared among many pages in your application. You don't need to see the details of these sections when you're concentrating on a particular page.
+
+TIP: For content that is shared among all pages in your application, you can use partials directly from layouts.
+
+==== Passing Local Variables
+
+You can also pass local variables into partials, making them even more powerful and flexible. For example, you can use this technique to reduce duplication between new and edit pages, while still keeping a bit of distinct content:
+
+[source, html]
+-------------------------------------------------------
+new.rhtml.erb:
+
+<h1>New zone</h1>
+<%= error_messages_for :zone %>
+<%= render :partial => "form", :locals => { :button_label => "Create zone", :zone => @zone } %>
+
+edit.html.erb:
+
+<h1>Editing zone</h1>
+<%= error_messages_for :zone %>
+<%= render :partial => "form", :locals => { :button_label => "Update zone", :zone => @zone } %>
+
+_form.html.erb:
+
+<% form_for(@zone) do |f| %>
+ <p>
+ <b>Zone name</b><br />
+ <%= f.text_field :name %>
+ </p>
+ <p>
+ <%= f.submit button_label %>
+ </p>
+<% end %>
+-------------------------------------------------------
+
+Although the same partial will be rendered into both views, the label on the submit button is controlled by a local variable passed into the partial.
+
+==== Rendering Collections
+
+Partials are very useful in rendering collections. When you pass a collection to a partial via the +:collection+ option, the partial will be inserted once for each member in the collection:
+
+[source, html]
+-------------------------------------------------------
+index.rhtml.erb:
+
+<h1>Products</h1>
+<%= render :partial => "product", :collection => @products %>
+
+_product.html.erb:
+
+<p>Product Name: <%= product.name %></p>
+-------------------------------------------------------
+
+When a partial is called with a pluralized collection, then the individual instances of the partial have access to the member of the collection being rendered via a singularized variable. In this case, the collection is +@products+, and within the +_product+ partial, you can refer to +product+ to get the instance that is being rendered.
== Changelog ==
http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/15[Lighthouse ticket]
-* September 20, 2008: First draft by link:../authors.html#mgunderloy[Mike Gunderloy] (not yet approved for publication)
+* September 28, 2008: First draft by link:../authors.html#mgunderloy[Mike Gunderloy] (not yet approved for publication)
@@ -98,3 +98,13 @@ TODO: Insert some description here.
***********************************************************
TODO: Insert some description here. No Lighthouse ticket.
***********************************************************
+
+.link:actionview/layouts_and_debugging.html[Layouts and Rendering in Rails]
+***********************************************************
+link:http://rails.lighthouseapp.com/projects/16213/tickets/15[Lighthouse Ticket]
+
+This guide covers the basic layout features of Action Controller and Action View,
+including rendering and redirecting, using +content_for_ blocks, and working
+with partials.
+***********************************************************
+

0 comments on commit a799425

Please sign in to comment.