4.1 导言
从前一章得知,即使完全不懂 Ruby 语言,我们也可以创建 Rails 应用的骨架,以及编写测试。我们依赖于书中提供的测试代码,得到错误信息,然后让测试组件通过。但是我们不能总是这样,所以这一章暂时不讲网站开发,而要正视我们的短肋——Ruby 语言。
前一章末尾我们修改了几乎是静态内容的页面,让它们使用 Rails 布局,去除视图中的重复。我们使用的布局如代码清单 4.1 所示(和代码清单 3.32 一样)。
代码清单 4.1:演示应用的网站布局
app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
<head>
<title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title>
<%= stylesheet_link_tag 'application', media: 'all',
'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= csrf_meta_tags %>
</head>
<body>
<%= yield %>
</body>
</html>
我们把注意力集中在上述代码中的这一行:
<%= stylesheet_link_tag "application", media: "all",
"data-turbolinks-track" => true %>
这行代码使用 Rails 内置的方法 stylesheet_link_tag
(详细信息参见 Rails API 文档),在所有媒介类型中引入 application.css
。对有经验的 Rails 开发者来说,这行代码看起来很简单,但是其中至少有四个 Ruby 知识点可能会让你困惑:内置的 Rails 方法,调用方法时不用括号,符号和哈希。这几点本章都会介绍。
Rails 除了提供很多内置的方法供我们在视图中使用之外,还允许我们自己定义。自己定义的方法叫辅助方法(helper)。为了说明如何自己定义辅助方法,我们来看看代码清单 4.1 中标题那一行:
<%= yield(:title) %> | Ruby on Rails Tutorial Sample App
这行代码要求每个视图都要使用 provide
方法定义标题,例如:
<% provide(:title, "Home") %>
<h1>Sample App</h1>
<p>
This is the home page for the
<a href="http://www.railstutorial.org/">Ruby on Rails Tutorial</a>
sample application.
</p>
那么,如果我们不提供标题会怎样呢?标题一般都包含一个公共部分,如果想更具体些,可以再加上变动的部分。我们在布局中用了个小技巧,基本上已经实现了这样的标题。如果在视图中不调用 provide
方法,也就是不提供变动的部分,那么得到的标题会变成:
| Ruby on Rails Tutorial Sample App
标题中有公共部分,但前面还显示了竖线。
为了解决这个问题,我们要自定义一个辅助方法,命名为 full_title
。如果视图中没有定义页面的标题,full_title
返回标题的公共部分,即“Ruby on Rails Tutorial Sample App”;如果定义了,则在变动部分后面加上一个竖线,如代码清单 4.2 所示。[1]
代码清单 4.2:定义 full_title
辅助方法
app/helpers/application_helper.rb
module ApplicationHelper
# 根据所在的页面返回完整的标题
def full_title(page_title = '')
base_title = "Ruby on Rails Tutorial Sample App"
if page_title.empty?
base_title
else
page_title + " | " + base_title
end
end
end
现在,这个辅助方法定义好了,我们可以用它来简化布局。把下面这行:
<title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title>
改成:
<title><%= full_title(yield(:title)) %></title>
如代码清单 4.3 所示。
代码清单 4.3:使用 full_title
辅助方法的网站布局 GREEN
app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
<head>
<title><%= full_title(yield(:title)) %></title>
<%= stylesheet_link_tag 'application', media: 'all',
'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= csrf_meta_tags %>
</head>
<body>
<%= yield %>
</body>
</html>
为了让这个辅助方法起作用,我们要在首页的视图中把不必要的单词“Home”删掉,只保留标题的公共部分。首先,我们要修改测试代码,如代码清单 4.4 所示,确认标题中没有 "Home"
。
代码清单 4.4:修改首页的标题测试 RED
test/controllers/static_pages_controller_test.rb
require 'test_helper'
class StaticPagesControllerTest < ActionController::TestCase
test "should get home" do
get :home
assert_response :success
assert_select "title", "Ruby on Rails Tutorial Sample App" end
test "should get help" do
get :help
assert_response :success
assert_select "title", "Help | Ruby on Rails Tutorial Sample App"
end
test "should get about" do
get :about
assert_response :success
assert_select "title", "About | Ruby on Rails Tutorial Sample App"
end
end
我们要运行测试组件,确认有一个测试失败:
代码清单 4.5:RED
$ bundle exec rake test
3 tests, 6 assertions, 1 failures, 0 errors, 0 skips
为了让测试通过,我们要把首页视图中的 provide
那行删除,如代码清单 4.6 所示。
代码清单 4.6:没定义页面标题的首页视图 GREEN
app/views/static_pages/home.html.erb
<h1>Sample App</h1>
<p>
This is the home page for the
<a href="http://www.railstutorial.org/">Ruby on Rails Tutorial</a>
sample application.
</p>
现在测试应该可以通过了:
代码清单 4.7:GREEN
$ bundle exec rake test
(注意,之前运行 rake test
时都显示了通过和失败测试的数量,为了行文简洁,从这以后都会省略这些数据。)
和引入应用的样式表那行代码一样,代码清单 4.2 的内容对有经验的 Rails 开发者来说也很简单,但其中很多重要的 Ruby 知识:模块,方法定义,可选的方法参数,注释,本地变量赋值,布尔值,流程控制,字符串拼接和返回值。本章会一一介绍这些知识。