ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# 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 ``` <!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 文档](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") %> <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](#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 ``` 现在,这个辅助方法定义好了,我们可以用它来简化布局。把下面这行: ``` <title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title> ``` 改成: ``` <title><%= full_title(yield(:title)) %></title> ``` 如[代码清单 4.3](#listing-application-layout-full-title) 所示。 ##### 代码清单 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](#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 ``` <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](#listing-title-helper) 的内容对有经验的 Rails 开发者来说也很简单,但其中很多重要的 Ruby 知识:模块,方法定义,可选的方法参数,注释,本地变量赋值,布尔值,流程控制,字符串拼接和返回值。本章会一一介绍这些知识。