Update: Oct-28-2011
layout的加载和覆盖问题
之前只是明确知道globe级别的layout会被controller级别的layout给覆盖了
实际上controller级别和globe级别的layout也会被share级别或者action级别的layout给覆盖掉
比如,有application layout,有admin layout,在admin controller里写了
layout 'application', :only => [:index]
那么,其它的action,会没有layout
Layout应该放在app/views/layouts下,我们的文件名是standard.rhtml
<!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">
<head>
<meta http-equiv="Content-Type" content="text/html;.
charset=iso-8859-1" />
<meta http-equiv="Content-Language" content="en-us" />
<title>Library Info System</title>
<%= stylesheet_link_tag "style" %>
</head>
<body id="library">
<div id="container">
<div id="header">
<h1>Library Info System</h1>
<h3>Library powered by Ruby on Rails</h3>
</div>
<div id="content">
<%= yield -%>
</div>
<div id="sidebar"></div>
</div>
</body>
</html>
上面的代码都是标准html来描述页面,只有两行不是link行是加载css,yield是ruby的块调用,用来输出框架内的内容
controller部分:
#book_controller.rb
class BookController < ApplicationController
layout 'standard'#表明我们将要调用standard.rhtml作为layout
def list
@books = Book.find(:all)
end
...................
打开浏览器访问,我们可以看到如下节目,说明已经加载内容。
然后,添加CSS样式描述到如下目录/public/stylesheets
body {
font-family: Helvetica, Geneva, Arial, sans-serif;
font-size: small;
font-color: #000;
background-color: #fff;
}
a:link, a:active, a:visited {
color: #CD0000;
}
input {
margin-bottom: 5px;
}
p {
line-height: 150%;
}
div#container {
width: 760px;
margin: 0 auto;
}
div#header {
text-align: center;
padding-bottom: 15px;
}
div#content {
float: left;
width: 450px;
padding: 10px;
}
div#content h3 {
margin-top: 15px;
}
ul#books {
list-style-type: none;
}
ul#books li {
line-height: 140%;
}
div#sidebar {
width: 200px;
margin-left: 480px;
}
ul#subjects {
width: 700px;
text-align: center;
padding: 5px;
background-color: #ececec;
border: 1px solid #ccc;
margin-bottom: 20px;
}
ul#subjects li {
display: inline;
padding-left: 5px;
}
你应该看到如下,界面是我们要的:
当然,上面的示例是标准用法,也是最普遍的用法。实际上,下面是hideto老大的,详细说明,2007年的相当经典,
http://www.rubyeye.com/topic/106623实在于心不忍,所以,转回来啦
一般来说layout有如下五种:
gobal layout,controller layout,shared layout,dynamic layout,action layout
假设我们有一个views/projects/index.rhtml页面:
<h2>Projects</h2>
<ul>
<% for project in @projects %>
<li><%= project.name %></li>
<% end %>
</ul>
<h2>Projects</h2>
<ul>
<% for project in @projects %>
<li><%= project.name %></li>
<% end %>
</ul>
下面来看看各种layout的用法。
1,global layout
添加views/layouts/application.rhtml:
<h1>Application Layout!</h1>
<%= yield %>
<h1>Application Layout!</h1>
<%= yield %>
在layouts目录下添加application.rhtml即可,<%= yield %>即输出我们的projects/index.rhtml页面
由于我们的controller都继承自ApplicationController,所以application.rhtml会先解析
2,controller layout
添加views/layouts/projects.rhtml:
<h1>Projects Layout!</h1>
<%= yield %>
<h1>Projects Layout!</h1>
<%= yield %>
道理同上,ProjectsController当然会使用同名的projects.rhtml作layout了
注意的是controller layout会覆盖global layout
3,shared layout
添加views/layouts/admin.rhtml:
<h1>Admin Layout!</h1>
<%= yield %>
<h1>Admin Layout!</h1>
<%= yield %>
我们建立了admin layout,然后在需要使用该layout的controller中指定即可:
class ProjectsController < ApplicationController
layout "admin"
def index
@projects = Project.find(:all)
end
end
class ProjectsController < ApplicationController
layout "admin"
def index
@projects = Project.find(:all)
end
end
4,dynamic layout
有时候我们需要根据不同的用户角色来使用不同的layout,比如管理员和一般用户,比如博客换肤(也可以用更高级的theme-generator)
class ProjectsController < ApplicationController
layout :user_layout
def index
@projects = Project.find(:all)
end
protected
def user_layout
if current_user.admin?
"admin"
else
"application"
end
end
end
class ProjectsController < ApplicationController
layout :user_layout
def index
@projects = Project.find(:all)
end
protected
def user_layout
if current_user.admin?
"admin"
else
"application"
end
end
end
5,action layout
在action中指定layout即可:
class ProjectsController < ApplicationController
layout :user_layout
def index
@projects = Project.find(:all)
render :layout => 'projects'
end
protected
def user_layout
if current_user.admin?
"admin"
else
"application"
end
end
end
class ProjectsController < ApplicationController
layout :user_layout
def index
@projects = Project.find(:all)
render :layout => 'projects'
end
protected
def user_layout
if current_user.admin?
"admin"
else
"application"
end
end
end
上面的index方法指定使用projects layout,当然我们也可以指定不使用layout,如printable页面:
def index
@projects = Project.find(:all)
render :layout => false
end
def index
@projects = Project.find(:all)
render :layout => false
end
需要注意的是,这5种layout会按顺序后面的覆盖前面的layout