3.4 有点动态内容的页面
最后更新于:2022-04-01 22:28:17
Hello, world!
``` 这段代码的最顶部是“文档类型声明”(document type declaration,简称 doctype),告诉浏览器使用哪个 HTML 版本(本例使用 [HTML5](http://en.wikipedia.org/wiki/HTML5))[[8](#fn-8)]。随后是 `head` 部分,包含一个 `title` 标签,其中的内容是“Greeting”。然后是 `body` 部分,包含一个 `p` 标签(段落),其中的内容是“Hello, world!”。(内容的缩进是可选的,HTML 不会特别对待空白,制表符和空格都会被忽略,但缩进可以让文档结构更清晰。) 我们要使用 `assert_select` 方法分别为[表 3.2](#table-static-pages) 中的每个标题编写简单的测试,合并到[代码清单 3.13](#listing-about-test) 的测试中。`assert_select` 方法的作用是检查有没有指定的 HTML 标签。这种方法有时也叫“选择符”,从方法名可以看出这一点。[[9](#fn-9)] ``` assert_select "title", "Home | Ruby on Rails Tutorial Sample App" ``` 这行代码的作用是检查有没有 `<title>` 标签,以及其中的内容是不是字符串“Home | Ruby on Rails Tutorial Sample App”。把这样的代码分别放到三个页面的测试中,得到的结果如[代码清单 3.22](#listing-title-tests) 所示。 ##### 代码清单 3.22:加入标题测试后的静态页面控制器测试 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", "Home | 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 ``` (如果你觉得在标题中重复使用“Ruby on Rails Tutorial Sample App”不妥,可以看一下 [3.6 节](#mostly-static-pages-exercises)的练习。) 写好测试之后,应该确认一下现在测试组件是失败的(**RED**): ##### 代码清单 3.23:**RED** ``` $ bundle exec rake test 3 tests, 6 assertions, 3 failures, 0 errors, 0 skips ``` ## 3.4.2 添加页面标题(变绿) 现在,我们要为每个页面添加标题,让前一节的测试通过。参照[代码清单 3.21](#listing-html-structure) 中的 HTML 结构,把[代码清单 3.9](#listing-custom-home-page) 中的首页内容换成[代码清单 3.24](#listing-home-view-full-html) 中的内容。 ##### 代码清单 3.24:具有完整 HTML 结构的首页 RED app/views/static_pages/home.html.erb ```Sample App
This is the home page for the Ruby on Rails Tutorial sample application.
``` 修改之后,首页如[图 3.6](#fig-home-view-full-html) 所示。[[10](#fn-10)] ![home view full html](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-11_5732bcf7efa31.png)图 3.6:添加标题后的首页 然后使用类似的方式修改“帮助”页面和“关于”页面,得到的代码如[代码清单 3.25](#listing-help-view-full-html) 和[代码清单 3.26](#listing-about-view-full-html) 所示。 ##### 代码清单 3.25:具有完整 HTML 结构的“帮助”页面 RED app/views/static_pages/help.html.erb ```Help
Get help on the Ruby on Rails Tutorial at the Rails Tutorial help section. To get help on this sample app, see the Ruby on Rails Tutorial book.
``` ##### 代码清单 3.26:具有完整 HTML 结构的“关于”页面 GREEN app/views/static_pages/about.html.erb ```About
The Ruby on Rails Tutorial is a book and screencast series to teach web development with Ruby on Rails. This is the sample application for the tutorial.
``` 现在,测试组件能通过了(**GREEN**): ##### 代码清单 3.27:**GREEN** ``` $ bundle exec rake test 3 tests, 6 assertions, 0 failures, 0 errors, 0 skips ``` ## 3.4.3 布局和嵌入式 Ruby(重构) 到目前为止,本节已经做了很多事情,我们使用 Rails 控制器和动作生成了三个可用的页面,不过这些页面中的内容都是纯静态的 HTML,没有体现出 Rails 的强大之处。而且,代码中有着大量重复: * 页面的标题几乎(但不完全)是一模一样的; * 每个标题中都有“Ruby on Rails Tutorial Sample App”; * 整个 HTML 结构在每个页面都重复地出现了。 重复的代码违反了很重要的“不要自我重复”(Don’t Repeat Yourself,简称 DRY)原则。本节要遵照 DRY 原则,去掉重复的代码。最后,我们要运行前一节编写的测试,确认显示的标题仍然正确。 不过,去除重复的第一步却是要增加一些代码,让页面的标题看起来是一样的。这样我们就能更容易地去掉重复的代码了。 在这个过程中,要在视图中使用嵌入式 Ruby(Embedded Ruby)。既然首页、“帮助”页面和“关于”页面的标题中有一个变动的部分,那我们就使用 Rails 提供的一个特别的函数 `provide`,在每个页面中设定不同的标题。通过把 `home.html.erb` 视图中标题的“Home”换成[代码清单 3.28](#listing-home-view-erb-title) 所示的代码,我们可以看一下这个函数的作用。 ##### 代码清单 3.28:标题中使用了嵌入式 Ruby 代码的首页视图 GREEN app/views/static_pages/home.html.erb ``` <% provide(:title, "Home") %>Sample App
This is the home page for the Ruby on Rails Tutorial sample application.
``` 在这段代码中我们第一次使用了嵌入式 Ruby,或者简称 ERb。(现在你应该知道为什么 HTML 视图文件的扩展名是 `.html.erb` 了。)ERb 是为网页添加动态内容主要使用的模板系统。[[11](#fn-11)]下面的代码 ``` <% provide(:title, 'Home') %> ``` 通过 `<% … %>` 调用 Rails 中的 `provide` 函数,把字符串 `"Home"` 赋给 `:title`。[[12](#fn-12)]然后,在标题中,我们使用类似的符号 `<%= … %>`,通过 Ruby 的 `yield` 函数把标题插入模板中:[[13](#fn-13)] ```Help
Get help on the Ruby on Rails Tutorial at the Rails Tutorial help section. To get help on this sample app, see the Ruby on Rails Tutorial book.
``` ##### 代码清单 3.31:标题中使用了嵌入式 Ruby 代码的“关于”页面视图 GREEN app/views/static_pages/about.html.erb ``` <% provide(:title, "About") %>About
The Ruby on Rails Tutorial is a book and screencast series to teach web development with Ruby on Rails. This is the sample application for the tutorial.
``` 至此,我们把页面标题中的变动部分都换成了 ERb。现在,各个页面的内容类似下面这样: ``` <% provide(:title, "The Title") %>Sample App
This is the home page for the Ruby on Rails Tutorial sample application.
``` ##### 代码清单 3.34:去除完整的 HTML 结构后的“帮助”页面 GREEN app/views/static_pages/help.html.erb ``` <% provide(:title, "Help") %>Help
Get help on the Ruby on Rails Tutorial at the Rails Tutorial help section. To get help on this sample app, see the Ruby on Rails Tutorial book.
``` ##### 代码清单 3.35:去除完整的 HTML 结构后的“关于”页面 GREEN app/views/static_pages/about.html.erb ``` <% provide(:title, "About") %>About
The Ruby on Rails Tutorial is a book and screencast series to teach web development with Ruby on Rails. This is the sample application for the tutorial.
``` 修改这几个视图后,首页、“帮助”页面和“关于”页面显示的内容还和之前一样,但是没有多少重复内容了。 经验告诉我们,即便是十分简单的重构,也容易出错,所以才要认真编写测试组件。有了测试,我们就无需手动检查每个页面,看有没有错误。初期阶段手动检查还不算难,但是当应用不断变大之后,情况就不同了。我们只需验证测试组件是否还能通过即可: ##### 代码清单 3.36:**GREEN** ``` $ bundle exec rake test 3 tests, 6 assertions, 0 failures, 0 errors, 0 skips ``` 测试不能证明代码完全正确,但至少能提高正确的可能性,而且还提供了安全防护措施,避免以后出现问题。 ## 3.4.4 设置根路由 我们修改了网站中的页面,也顺利开始编写测试了,在继续之前,我们要设置应用的根路由。与 [1.3.4 节](chapter1.html#hello-world)和 [2.2.2 节](chapter2.html#mvc-in-action)的做法一样,我们要修改 `routes.rb` 文件,把根路径 `/` 指向我们选择的页面。这里我们要指向前面创建的首页。(我还建议把 [3.1 节](#sample-app-setup)添加的 `hello` 动作从应用的控制器中删除。)如[代码清单 3.37](#listing-home-root-route) 所示,我们要把自动生成的 `get` 规则([代码清单 3.5](#listing-pages-routes))改成: ``` root 'static_pages#home' ``` 我们把 `static_pages/home` 改成 `static_pages#home`,确保通过 `GET` 请求访问 `/` 时,会交给静态页面路由器中的 `home` 动作处理。修改路由后,首页如[图 3.7](#fig-home-root-route) 所示。(注意,修改路由之后,/static_pages/home 就无法访问了。) ##### 代码清单 3.37:把根路由指向首页 config/routes.rb ``` Rails.application.routes.draw do root 'static_pages#home' get 'static_pages/help' get 'static_pages/about' end ``` ![home root route](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-11_5732bcf810cf4.png)图 3.7:在根路由上显示的首页