Update: Oct-28-2011
layout的加载和覆盖问题
之前只是明确知道globe级别的layout会被controller级别的layout给覆盖了
实际上controller级别和globe级别的layout也会被share级别或者action级别的layout给覆盖掉
比如,有application layout,有admin layout,在admin controller里写了

Ruby代码
  1. layout 'application', :only => [:index]

那么,其它的action,会没有layout

Layout应该放在app/views/layouts下,我们的文件名是standard.rhtml

Html代码
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  2. "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  3. <html xmlns="http://www.w3.org/1999/xhtml">
  4. <head>
  5. <meta http-equiv="Content-Type" content="text/html;.
  6. charset=iso-8859-1" />
  7. <meta http-equiv="Content-Language" content="en-us" />
  8. <title>Library Info System</title>
  9. <%= stylesheet_link_tag "style" %>
  10. </head>
  11. <body id="library">
  12. <div id="container">
  13. <div id="header">
  14. <h1>Library Info System</h1>
  15. <h3>Library powered by Ruby on Rails</h3>
  16. </div>
  17. <div id="content">
  18. <%= yield -%>
  19. </div>
  20. <div id="sidebar"></div>
  21. </div>
  22. </body>
  23. </html>

上面的代码都是标准html来描述页面,只有两行不是link行是加载css,yield是ruby的块调用,用来输出框架内的内容

controller部分:

Ruby代码
  1. #book_controller.rb
  2. class BookController < ApplicationController
  3.    layout 'standard'#表明我们将要调用standard.rhtml作为layout
  4.    def list
  5.       @books = Book.find(:all)
  6.    end
  7. ...................

打开浏览器访问,我们可以看到如下节目,说明已经加载内容。

然后,添加CSS样式描述到如下目录/public/stylesheets

Html代码
  1. body {
  2.    font-family: Helvetica, Geneva, Arial, sans-serif;
  3.    font-size: small;
  4.    font-color: #000;
  5.    background-color: #fff;
  6. }
  7. a:link, a:active, a:visited {
  8.    color: #CD0000;
  9. }
  10. input {
  11.    margin-bottom: 5px;
  12. }
  13. p {
  14.    line-height: 150%;
  15. }
  16. div#container {
  17.    width: 760px;
  18.    margin: 0 auto;
  19. }
  20. div#header {
  21.    text-align: center;
  22.    padding-bottom: 15px;
  23. }
  24. div#content {
  25.    float: left;
  26.    width: 450px;
  27.    padding: 10px;
  28. }
  29. div#content h3 {
  30.    margin-top: 15px;
  31. }
  32. ul#books {
  33.    list-style-type: none;
  34. }
  35. ul#books li {
  36.    line-height: 140%;
  37. }
  38. div#sidebar {
  39.    width: 200px;
  40.    margin-left: 480px;
  41. }
  42. ul#subjects {
  43.    width: 700px;
  44.    text-align: center;
  45.    padding: 5px;
  46.    background-color: #ececec;
  47.    border: 1px solid #ccc;
  48.    margin-bottom: 20px;
  49. }
  50. ul#subjects li {
  51.    display: inline;
  52.    padding-left: 5px;
  53. }

你应该看到如下,界面是我们要的:

当然,上面的示例是标准用法,也是最普遍的用法。实际上,下面是hideto老大的,详细说明,2007年的相当经典

一般来说layout有如下五种:
gobal layout,controller layout,shared layout,dynamic layout,action layout

假设我们有一个views/projects/index.rhtml页面:

Ruby代码
  1. <h2>Projects</h2>
  2. <ul>
  3. <% for project in @projects %>
  4.   <li><%= project.name %></li>
  5. <% end %>
  6. </ul>
  7. <h2>Projects</h2>
  8. <ul>
  9. <% for project in @projects %>
  10.   <li><%= project.name %></li>
  11. <% end %>
  12. </ul>

下面来看看各种layout的用法。

1,global layout
添加views/layouts/application.rhtml:

Ruby代码
  1. <h1>Application Layout!</h1>
  2. <%= yield %>
  3. <h1>Application Layout!</h1>
  4. <%= yield %>

在layouts目录下添加application.rhtml即可,<%= yield %>即输出我们的projects/index.rhtml页面
由于我们的controller都继承自ApplicationController,所以application.rhtml会先解析

2,controller layout
添加views/layouts/projects.rhtml:

Ruby代码
  1. <h1>Projects Layout!</h1>
  2. <%= yield %>
  3. <h1>Projects Layout!</h1>
  4. <%= yield %>

道理同上,ProjectsController当然会使用同名的projects.rhtml作layout了
注意的是controller layout会覆盖global layout

3,shared layout
添加views/layouts/admin.rhtml:

Ruby代码
  1. <h1>Admin Layout!</h1>
  2. <%= yield %>
  3. <h1>Admin Layout!</h1>
  4. <%= yield %>

我们建立了admin layout,然后在需要使用该layout的controller中指定即可:

Ruby代码
  1. class ProjectsController < ApplicationController
  2.   layout "admin"
  3.   def index
  4.     @projects = Project.find(:all)
  5.   end
  6. end
  7. class ProjectsController < ApplicationController
  8.   layout "admin"
  9.   def index
  10.     @projects = Project.find(:all)
  11.   end
  12. end

4,dynamic layout
有时候我们需要根据不同的用户角色来使用不同的layout,比如管理员和一般用户,比如博客换肤(也可以用更高级的theme-generator)

Ruby代码
  1. class ProjectsController < ApplicationController
  2.   layout :user_layout
  3.   def index
  4.     @projects = Project.find(:all)
  5.   end
  6.   protected
  7.   def user_layout
  8.     if current_user.admin?
  9.       "admin"
  10.     else
  11.       "application"
  12.     end
  13.   end
  14. end
  15. class ProjectsController < ApplicationController
  16.   layout :user_layout
  17.   def index
  18.     @projects = Project.find(:all)
  19.   end
  20.   protected
  21.   def user_layout
  22.     if current_user.admin?
  23.       "admin"
  24.     else
  25.       "application"
  26.     end
  27.   end
  28. end

5,action layout
在action中指定layout即可:

Ruby代码
  1. class ProjectsController < ApplicationController
  2.   layout :user_layout
  3.   def index
  4.     @projects = Project.find(:all)
  5.     render :layout => 'projects'
  6.   end
  7.   protected
  8.   def user_layout
  9.     if current_user.admin?
  10.       "admin"
  11.     else
  12.       "application"
  13.     end
  14.   end
  15. end
  16. class ProjectsController < ApplicationController
  17.   layout :user_layout
  18.   def index
  19.     @projects = Project.find(:all)
  20.     render :layout => 'projects'
  21.   end
  22.   protected
  23.   def user_layout
  24.     if current_user.admin?
  25.       "admin"
  26.     else
  27.       "application"
  28.     end
  29.   end
  30. end

上面的index方法指定使用projects layout,当然我们也可以指定不使用layout,如printable页面:

Ruby代码
  1. def index
  2.   @projects = Project.find(:all)
  3.   render :layout => false
  4. end
  5. def index
  6.   @projects = Project.find(:all)
  7.   render :layout => false
  8. end

需要注意的是,这5种layout会按顺序后面的覆盖前面的layout