这次咱们聊聊页面布局文件。布局文件其实也是一个页面,用来定义一些公共的或者框架的页面结构。普通的页面文件再嵌入到布局文件预留的空间中来形成整个页面的样子。布局文件是可以在各个页面之间公用的公共资源。
全局范围布局文件
下面的页面列出所有的项目名称
<h2>Projects</h2>
<ul>
<% for project in @projects %>
<li><%= project.name %></li>
<% end %>
</ul>
这是一个常规简单的页面:
比如说,我们想为这个站点的每一个页面都增加一个页首、图标、导航菜单栏,就应该使用布局文件。布局文件的标准存放位置在/app/view/layouts
目录。在其中创建一个名为application.rhtml
[1]的应用全局布局文件。这个文件的布局规则将会作用域所有的控制器和页面请求中。我们把布局文件定义成:
<h1>Application Layout!</h1>
<%= yield %>
请注意第二行,yield
告诉布局文件说在这里应该是插入应用了这个布局文件的页面内容。重新刷新后可以看出,定义的布局已经生效了。
这么着定义的布局文件是全局范围的,将会作用于所有的页面上。实际应用中肯定还不能这么粗狂,还得定义一些特定于不同类型页面的布局文件。
特定于控制器的布局文件
通过把控制器的名称指定给布局文件,来将布局文件和控制器关联。这样一来,这个布局文件就会作用到所有指向这个控制器页面。比如说,在layouts
目录建立一个projects.rhtml
[2]文件意味着这个布局只在Project
对应的控制器生效。
<h1>Project Layout!</h1>
<%= yield %>
如果好几个控制器想共享一个布局文件该怎么办呢?比如说,我想共享名字叫admin
的那个布局文件。那就在控制器代码中明确指定吧:
class ProjectsController < ApplicationController
layout "admin"
def index
@projects = Project.find(:all)
end
end
在控制器中通过layout
方法指定的布局文件会覆盖通过文件名字规则指定的布局定义。
动态关联布局文件
也可以动态关联布局文件,比如说我们只是想让用户登录之后再让页面关联名为admin
的布局文件。可以通过给layout
方法传递参数的方式实现;定义一个与参数名相同的方法,方法逻辑中计算在什么时候应该使用哪个名字的布局文件即可。
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
通过render
方法,可以更加精细地设定哪个控制器的那个请求使用哪个布局文件。
def index
@projects = Project.find(:all)
render :layout => 'projects'
end
通过render
方法指定的布局文件会覆盖控制器关联布局文件的定义。想清空布局关联可以使用:
注: