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