<?xml version="1.0" encoding="iso-8859-1"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title>Module: ActionController::Layout::ClassMethods</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <meta http-equiv="Content-Script-Type" content="text/javascript" /> <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" /> <script type="text/javascript"> // <![CDATA[ function popupCode( url ) { window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400") } function toggleCode( id ) { if ( document.getElementById ) elem = document.getElementById( id ); else if ( document.all ) elem = eval( "document.all." + id ); else return false; elemStyle = elem.style; if ( elemStyle.display != "block" ) { elemStyle.display = "block" } else { elemStyle.display = "none" } return true; } // Make codeblocks hidden by default document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" ) // ]]> </script> </head> <body> <div id="classHeader"> <table class="header-table"> <tr class="top-aligned-row"> <td><strong>Module</strong></td> <td class="class-name-in-header">ActionController::Layout::ClassMethods</td> </tr> <tr class="top-aligned-row"> <td><strong>In:</strong></td> <td> <a href="../../../files/lib/action_controller/layout_rb.html"> lib/action_controller/layout.rb </a> <br /> </td> </tr> </table> </div> <!-- banner header --> <div id="bodyContent"> <div id="contextContent"> <div id="description"> <p> Layouts reverse the common pattern of including shared headers and footers in many templates to isolate changes in repeated setups. The inclusion pattern has pages that look like this: </p> <pre> <%= render "shared/header" %> Hello World <%= render "shared/footer" %> </pre> <p> This approach is a decent way of keeping common structures isolated from the changing content, but it‘s verbose and if you ever want to change the structure of these two includes, you‘ll have to change all the templates. </p> <p> With layouts, you can flip it around and have the common structure know where to insert changing content. This means that the header and footer are only mentioned in one place, like this: </p> <pre> // The header part of this layout <%= yield %> // The footer part of this layout </pre> <p> And then you have content pages that look like this: </p> <pre> hello world </pre> <p> At rendering time, the content page is computed and then inserted in the <a href="ClassMethods.html#M000069">layout</a>, like this: </p> <pre> // The header part of this layout hello world // The footer part of this layout </pre> <p> NOTE: The old notation for rendering the view from a <a href="ClassMethods.html#M000069">layout</a> was to expose the magic <tt>@content_for_layout</tt> instance variable. The preferred notation now is to use <tt>yield</tt>, as documented above. </p> <h2>Accessing shared variables</h2> <p> Layouts have access to variables specified in the content pages and vice versa. This allows you to have layouts with references that won‘t materialize before rendering time: </p> <pre> <h1><%= @page_title %></h1> <%= yield %> </pre> <p> …and content pages that fulfill these references <em>at</em> rendering time: </p> <pre> <% @page_title = "Welcome" %> Off-world colonies offers you a chance to start a new life </pre> <p> The result after rendering is: </p> <pre> <h1>Welcome</h1> Off-world colonies offers you a chance to start a new life </pre> <h2>Automatic <a href="ClassMethods.html#M000069">layout</a> assignment</h2> <p> If there is a template in <tt>app/views/layouts/</tt> with the same name as the current controller then it will be automatically set as that controller‘s <a href="ClassMethods.html#M000069">layout</a> unless explicitly told otherwise. Say you have a WeblogController, for example. If a template named <tt>app/views/layouts/weblog.erb</tt> or <tt>app/views/layouts/weblog.builder</tt> exists then it will be automatically set as the <a href="ClassMethods.html#M000069">layout</a> for your WeblogController. You can create a <a href="ClassMethods.html#M000069">layout</a> with the name <tt>application.erb</tt> or <tt>application.builder</tt> and this will be set as the default controller if there is no <a href="ClassMethods.html#M000069">layout</a> with the same name as the current controller and there is no <a href="ClassMethods.html#M000069">layout</a> explicitly assigned with the <tt><a href="ClassMethods.html#M000069">layout</a></tt> method. Nested controllers use the same folder structure for automatic <a href="ClassMethods.html#M000069">layout</a>. assignment. So an Admin::WeblogController will look for a template named <tt>app/views/layouts/admin/weblog.erb</tt>. Setting a <a href="ClassMethods.html#M000069">layout</a> explicitly will always override the automatic behaviour for the controller where the <a href="ClassMethods.html#M000069">layout</a> is set. Explicitly setting the <a href="ClassMethods.html#M000069">layout</a> in a parent class, though, will not override the child class‘s <a href="ClassMethods.html#M000069">layout</a> assignment if the child class has a <a href="ClassMethods.html#M000069">layout</a> with the same name. </p> <h2>Inheritance for layouts</h2> <p> Layouts are shared downwards in the inheritance hierarchy, but not upwards. Examples: </p> <pre> class BankController < ActionController::Base layout "bank_standard" class InformationController < BankController class VaultController < BankController layout :access_level_layout class EmployeeController < BankController layout nil </pre> <p> The InformationController uses "bank_standard" inherited from the BankController, the VaultController overwrites and picks the <a href="ClassMethods.html#M000069">layout</a> dynamically, and the EmployeeController doesn‘t want to use a <a href="ClassMethods.html#M000069">layout</a> at all. </p> <h2>Types of layouts</h2> <p> Layouts are basically just regular templates, but the name of this template needs not be specified statically. Sometimes you want to alternate layouts depending on runtime information, such as whether someone is logged in or not. This can be done either by specifying a method reference as a symbol or using an inline method (as a proc). </p> <p> The method reference is the preferred approach to variable layouts and is used like this: </p> <pre> class WeblogController < ActionController::Base layout :writers_and_readers def index # fetching posts end private def writers_and_readers logged_in? ? "writer_layout" : "reader_layout" end </pre> <p> Now when a new request for the index action is processed, the <a href="ClassMethods.html#M000069">layout</a> will vary depending on whether the person accessing is logged in or not. </p> <p> If you want to use an inline method, such as a proc, do something like this: </p> <pre> class WeblogController < ActionController::Base layout proc{ |controller| controller.logged_in? ? "writer_layout" : "reader_layout" } </pre> <p> Of course, the most common way of specifying a <a href="ClassMethods.html#M000069">layout</a> is still just as a plain template name: </p> <pre> class WeblogController < ActionController::Base layout "weblog_standard" </pre> <p> If no directory is specified for the template name, the template will by default be looked for in <tt>app/views/layouts/</tt>. Otherwise, it will be looked up relative to the template root. </p> <h2>Conditional layouts</h2> <p> If you have a <a href="ClassMethods.html#M000069">layout</a> that by default is applied to all the actions of a controller, you still have the option of rendering a given action or set of actions without a <a href="ClassMethods.html#M000069">layout</a>, or restricting a <a href="ClassMethods.html#M000069">layout</a> to only a single action or a set of actions. The <tt>:only</tt> and <tt>:except</tt> options can be passed to the <a href="ClassMethods.html#M000069">layout</a> call. For example: </p> <pre> class WeblogController < ActionController::Base layout "weblog_standard", :except => :rss # ... end </pre> <p> This will assign "weblog_standard" as the WeblogController‘s <a href="ClassMethods.html#M000069">layout</a> except for the <tt>rss</tt> action, which will not wrap a <a href="ClassMethods.html#M000069">layout</a> around the rendered view. </p> <p> Both the <tt>:only</tt> and <tt>:except</tt> condition can accept an arbitrary number of method references, so #<tt>:except => [ :rss, :text_only ]</tt> is valid, as is <tt>:except => :rss</tt>. </p> <h2>Using a different <a href="ClassMethods.html#M000069">layout</a> in the action render call</h2> <p> If most of your actions use the same <a href="ClassMethods.html#M000069">layout</a>, it makes perfect sense to define a controller-wide <a href="ClassMethods.html#M000069">layout</a> as described above. Sometimes you‘ll have exceptions where one action wants to use a different <a href="ClassMethods.html#M000069">layout</a> than the rest of the controller. You can do this by passing a <tt>:<a href="ClassMethods.html#M000069">layout</a></tt> option to the <tt>render</tt> call. For example: </p> <pre> class WeblogController < ActionController::Base layout "weblog_standard" def help render :action => "help", :layout => "help" end end </pre> <p> This will render the help action with the "help" <a href="ClassMethods.html#M000069">layout</a> instead of the controller-wide "weblog_standard" <a href="ClassMethods.html#M000069">layout</a>. </p> </div> </div> <div id="method-list"> <h3 class="section-bar">Methods</h3> <div class="name-list"> <a href="#M000069">layout</a> </div> </div> </div> <!-- if includes --> <div id="section"> <!-- if method_list --> <div id="methods"> <h3 class="section-bar">Public Instance methods</h3> <div id="method-M000069" class="method-detail"> <a name="M000069"></a> <div class="method-heading"> <a href="ClassMethods.src/M000069.html" target="Code" class="method-signature" onclick="popupCode('ClassMethods.src/M000069.html');return false;"> <span class="method-name">layout</span><span class="method-args">(template_name, conditions = {}, auto = false)</span> </a> </div> <div class="method-description"> <p> If a <a href="ClassMethods.html#M000069">layout</a> is specified, all rendered actions will have their result rendered when the <a href="ClassMethods.html#M000069">layout</a> <tt>yield</tt>s. This <a href="ClassMethods.html#M000069">layout</a> can itself depend on instance variables assigned during action performance and have access to them as any normal template would. </p> </div> </div> </div> </div> <div id="validator-badges"> <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p> </div> </body> </html>