Readit 功能测试与 Rails 插件使用指南
1. Readit 功能测试
在 Readit 应用中,为确保各项功能的正常运行,进行了一系列的测试。
1.1 关联投票测试
首先是关联投票测试,代码如下:
test "voted on association" do
assert_equal [ stories(:one) ],
users(:glenn).stories_voted_on
end
此测试依赖于固定数据,用于断言测试用户投票的故事列表是否与预期一致。
1.2 故事控制器测试
在故事控制器(StoriesController)中,添加了许多需要测试的功能,测试相对复杂。
-
故事索引页面测试
:
- 为确认故事列表操作(索引和回收站)能从数据库中选取正确的记录,在
test/fixtures/stories.yml
中添加新故事:
promoted:
name: What is a Debugger?
link: http://en.wikipedia.org/wiki/Debugger/
user: john
votes_count: 5
- 修改现有测试并添加新测试以确保模板正确渲染:
class StoriesControllerTest < ActionDispatch::IntegrationTest
# 其他测试方法...
test "gets stories" do
get stories_path
assert_response :success
assert response.body.include?(stories(:promoted).name)
end
test "gets bin" do
get bin_stories_path
assert_response :success
assert response.body.include?(stories(:two).name)
end
# 其他测试方法...
end
这两个测试调用各自的操作,检查请求是否成功响应,并确认是否渲染了合适的故事。
-
路由配置测试
:
添加测试以确认路由配置更改是否正常工作:
test "story index is default" do
assert_recognizes({ controller: "stories",
action: "index" }, "/")
end
该断言确认对根路径“/”的请求会被路由到 StoriesController 的索引操作。
-
页面标题测试
:
test "shows story on index" do
get stories_path
assert_select 'h2', 'Showing 1 frontpage story'
assert_select 'div#content div.story', count: 1
end
test "show stories in bin" do
get bin_stories_path
assert_select 'h2', 'Showing 2 upcoming stories'
assert_select 'div#content div.story', count: 2
end
这些测试检查索引操作的视图,确认标题标签包含正确的标题和预期数量的故事。
-
故事提交表单测试
:
test "new shows new form" do
login_user
get :new
assert_select 'form p', count: 3
end
此测试检查故事提交表单中的
<p>
元素数量是否符合预期。
-
故事显示页面测试
:
test "show story vote elements" do
login_user
get story_path(stories(:one))
# 方法体...
end
test "does not show vote button if not logged in" do
get story_path(stories(:one))
assert_select 'div#vote_link', false
end
这些测试处理未登录用户看不到投票按钮的情况。
-
导航菜单测试
:
test "show navigation menu" do
get stories_path
assert_select 'ul#navigation li', 3
end
由于导航菜单添加了一个项目,所以检查列表项数量是否为 3。
-
故事提交者链接文本测试
:
test "show story submitter" do
get story_path(stories(:one))
assert_select 'p.submitted_by span a', 'Glenn Goodrich'
end
此测试确保故事页面上的故事提交者链接到提交者的用户页面。
1.3 投票控制器测试
由于投票程序修改为仅对登录用户可用,需要修改现有测试并添加新测试:
test "stores user with vote" do
post story_votes_path(stories(:two))
stories(:two).reload
assert_equal users(:glenn), stories(:two).votes.last.user
end
该测试确认投票操作会存储当前用户与提交的投票。
1.4 用户控制器测试
为覆盖用户控制器(UsersController)中用户页面的功能,添加了三个测试:
class UsersControllerTest < ActionController::TestCase
test "show user" do
get user_path(users(:glenn))
assert_response :success
assert response.body.include?(users(:glenn).name)
end
test "show submitted stories" do
get user_path(users(:glenn))
assert_select 'div#stories_submitted div.story', count: 2
end
test "show stories voted on" do
get user_path(users(:glenn))
assert_select 'div#stories_voted_on div.story', count: 1
end
end
这些测试确认显示操作能找到正确的用户,并在页面上正确显示用户提交的故事和投票历史。
1.5 完整测试套件运行
完成所有测试添加后,运行完整测试套件:
$ rails test
测试结果显示,所有测试均通过,表明 Readit 应用状态良好。
2. Rails 插件
Rails 插件是可以添加到应用中以扩展其功能的组件。
2.1 插件概述
插件可用于扩展 ActiveRecord 功能、提供辅助方法、引入新的模板引擎等。可以通过在 Rubygems 或 Ruby Toolbox 网站上搜索“Rails”来找到现有的插件。插件以 gem 形式分发,可通过将其添加到 Gemfile 并运行
bundle install
来引入应用。
2.2 标签功能插件:acts - as - taggable - on
为了给 Readit 应用添加标签功能,选择使用
acts - as - taggable - on
插件。
-
插件历史
:该插件有一段发展历史,最初 David Heinemeier Hansson 开发了
acts_as_taggable作为概念验证,后被弃用。Jonathan Viney 开发了acts_as_taggable_on_steroids,最终 Michael Bleigh 形成了acts - as - taggable - on并持续开发。 -
acts_as_*命名约定 :在 Rails 插件仓库中,有许多acts_as_*形式的功能扩展,这些扩展能让模型具备特定功能,通常只需一行代码即可启用。例如acts_as_list可使对象位于扁平列表中,acts_as_tree可创建复杂的树状系统。而acts - as - taggable - on能让模型可标签化,它自带ActsAsTaggableOn::Tag模型类,并能将以空格分隔的标签列表解析为单独的模型对象。 -
命名空间安全措施
:
Tag类被命名空间为ActsAsTaggableOn,这是 Ruby 社区的最佳实践,可避免不同 gem 或库中的类名冲突。
2.3 安装
acts - as - taggable - on
插件
安装步骤如下:
1. 进入应用根目录,在 Gemfile 中添加以下内容:
gem "acts-as-taggable-on", "~> 4.0"
~>
表示希望使用 4.x 系列的任何版本。
2. 运行以下命令安装插件:
$ bundle install
安装完成后,会有来自
acts - as - taggable - on
gem 的安装后消息。
2.4 创建插件迁移
为了让用户能给提交的故事添加标签,需要为故事模型添加可标签化功能。由于插件使用了新模型,需要创建迁移来创建新表。
-
生成迁移文件
:
$ rails acts_as_taggable_on_engine:install:migrations
此命令会将五个迁移文件复制到
db/migrate
目录,这些文件将创建
acts - as - taggable - on
使用的表和数据库索引。
-
迁移代码
:
class ActsAsTaggableOnMigration < ActiveRecord::Migration
def self.up
create_table :tags do |t|
t.string :name
end
create_table :taggings do |t|
t.references :tag
# 确保创建的列足够长以存储所需的类名
t.references :taggable, polymorphic: true
t.references :tagger, polymorphic: true
# 限制长度以防止 MySQL MyISAM 表类型的索引长度错误
t.string :context, limit: 128
t.datetime :created_at
end
add_index :taggings, :tag_id
add_index :taggings, [:taggable_id, :taggable_type, :context]
end
def self.down
drop_table :taggings
drop_table :tags
end
end
该迁移创建了
tags
和
taggings
表,
tags
表存储标签名称,
taggings
表存储标签与被标签对象之间的映射关系。其中
polymorphic
表示多态,允许一个表与多个不同类型的模型关联。在给故事模型添加
acts - as - taggable - on
功能之前,需要应用刚刚生成的迁移。
总结
通过对 Readit 应用进行全面的功能测试,确保了各项功能的稳定性。同时,借助 Rails 插件
acts - as - taggable - on
,可以为应用添加标签功能,进一步扩展应用的功能。在后续开发中,可以继续添加更多功能,并不断完善测试套件。
以下是一个简单的 mermaid 流程图,展示了安装
acts - as - taggable - on
插件的流程:
graph LR
A[进入应用根目录] --> B[在 Gemfile 中添加插件]
B --> C[运行 bundle install]
C --> D[生成迁移文件]
D --> E[应用迁移]
| 步骤 | 操作 | 代码示例 |
|---|---|---|
| 1 | 进入应用根目录 | cd 应用根目录路径 |
| 2 | 在 Gemfile 中添加插件 | gem “acts-as-taggable-on”, “~> 4.0” |
| 3 | 运行 bundle install | bundle install |
| 4 | 生成迁移文件 | rails acts_as_taggable_on_engine:install:migrations |
| 5 | 应用迁移 | rails db:migrate |
Readit 功能测试与 Rails 插件使用指南
3. 应用
acts - as - taggable - on
插件到 Readit
在完成
acts - as - taggable - on
插件的安装和迁移后,接下来需要将其应用到 Readit 的故事模型中,让用户能够为故事添加标签。
3.1 使故事模型可标签化
要让故事模型支持标签功能,需要在
Story
模型文件中添加相应的代码。打开
app/models/story.rb
文件,添加如下代码:
class Story < ApplicationRecord
acts_as_taggable_on :tags
end
acts_as_taggable_on :tags
这行代码启用了故事模型的标签功能,允许用户为故事添加标签。
3.2 更新故事提交表单
为了让用户能够在提交故事时添加标签,需要更新故事提交表单。打开
app/views/stories/_form.html.erb
文件,添加一个标签输入字段:
<%= form.label :tag_list, "Tags (separated by spaces or commas)" %>
<%= form.text_field :tag_list %>
这个输入字段允许用户输入以空格或逗号分隔的标签列表。
3.3 处理标签数据
在
StoriesController
中,需要处理用户提交的标签数据。打开
app/controllers/stories_controller.rb
文件,更新
create
和
update
方法,确保标签数据被正确保存:
class StoriesController < ApplicationController
def create
@story = Story.new(story_params)
if @story.save
redirect_to @story, notice: 'Story was successfully created.'
else
render :new
end
end
def update
if @story.update(story_params)
redirect_to @story, notice: 'Story was successfully updated.'
else
render :edit
end
end
private
def story_params
params.require(:story).permit(:name, :link, :user_id, :tag_list)
end
end
在
story_params
方法中,添加了
:tag_list
字段,确保标签数据能够被正确传递和保存。
3.4 显示故事标签
在故事显示页面,需要显示故事的标签。打开
app/views/stories/show.html.erb
文件,添加如下代码:
<p>
<strong>Tags:</strong>
<%= @story.tag_list.join(', ') %>
</p>
这行代码将故事的标签列表以逗号分隔的形式显示在页面上。
4. 测试标签功能
为了确保标签功能正常工作,需要编写相应的测试用例。
4.1 测试故事创建时的标签保存
在
test/controllers/stories_controller_test.rb
文件中,添加如下测试用例:
test "creates story with tags" do
login_user
post stories_path, params: { story: { name: 'Test Story', link: 'http://example.com', tag_list: 'ruby, rails' } }
assert_redirected_to story_path(assigns(:story))
story = assigns(:story)
assert_equal ['ruby', 'rails'], story.tag_list
end
这个测试用例模拟用户创建一个带有标签的故事,并验证标签是否被正确保存。
4.2 测试故事更新时的标签更新
同样在
test/controllers/stories_controller_test.rb
文件中,添加如下测试用例:
test "updates story with new tags" do
login_user
story = stories(:one)
patch story_path(story), params: { story: { tag_list: 'newtag1, newtag2' } }
assert_redirected_to story_path(story)
story.reload
assert_equal ['newtag1', 'newtag2'], story.tag_list
end
这个测试用例模拟用户更新一个故事的标签,并验证标签是否被正确更新。
5. 进一步扩展 Readit
虽然已经为 Readit 添加了标签功能,但还有许多其他功能可以进一步扩展。
5.1 用户注册和登录功能
可以添加用户注册和登录功能,让用户能够创建自己的账户并登录。可以使用 Devise 等宝石来实现这一功能。具体步骤如下:
1. 在 Gemfile 中添加 Devise 宝石:
gem 'devise'
-
运行
bundle install安装宝石。 - 生成 Devise 配置:
rails generate devise:install
- 生成用户模型:
rails generate devise User
- 运行迁移:
rails db:migrate
- 在视图和控制器中添加相应的注册和登录页面及逻辑。
5.2 故事评论功能
可以添加故事评论功能,让用户能够对故事发表评论。可以创建一个
Comment
模型,并在故事显示页面添加评论表单和评论列表。具体步骤如下:
1. 生成
Comment
模型:
rails generate model Comment content:text story:references user:references
- 运行迁移:
rails db:migrate
-
在
Story模型中关联评论:
class Story < ApplicationRecord
has_many :comments
end
-
在
User模型中关联评论:
class User < ApplicationRecord
has_many :comments
end
- 在故事显示页面添加评论表单和评论列表:
<h2>Comments</h2>
<% @story.comments.each do |comment| %>
<p><%= comment.content %></p>
<p>By <%= comment.user.name %></p>
<% end %>
<%= form_with(model: [@story, @story.comments.build], local: true) do |form| %>
<%= form.label :content %>
<%= form.text_area :content %>
<%= form.submit %>
<% end %>
5.3 投票限制功能
可以添加投票限制功能,确保用户只能对每个故事投票一次。可以在
Vote
模型中添加唯一约束,并在投票时进行检查。具体步骤如下:
1. 在
Vote
模型中添加唯一约束:
class Vote < ApplicationRecord
validates_uniqueness_of :user_id, scope: :story_id
end
-
在
VotesController中添加投票检查逻辑:
class VotesController < ApplicationController
def create
@story = Story.find(params[:story_id])
if @story.votes.where(user_id: current_user.id).exists?
redirect_to @story, alert: 'You have already voted for this story.'
else
@vote = @story.votes.create(user: current_user)
redirect_to @story, notice: 'Vote cast successfully.'
end
end
end
总结
通过对 Readit 应用进行功能测试和添加
acts - as - taggable - on
插件,我们不仅确保了应用的稳定性,还为应用添加了强大的标签功能。同时,我们还探讨了如何进一步扩展 Readit,如添加用户注册和登录、故事评论和投票限制等功能。在开发过程中,要不断完善测试套件,确保新功能的正确性和稳定性。
以下是一个 mermaid 流程图,展示了扩展 Readit 功能的步骤:
graph LR
A[添加标签功能] --> B[添加用户注册和登录功能]
B --> C[添加故事评论功能]
C --> D[添加投票限制功能]
| 扩展功能 | 操作步骤 |
|---|---|
| 添加标签功能 | 1. 使故事模型可标签化;2. 更新故事提交表单;3. 处理标签数据;4. 显示故事标签;5. 编写测试用例 |
| 添加用户注册和登录功能 | 1. 添加 Devise 宝石;2. 生成 Devise 配置;3. 生成用户模型;4. 运行迁移;5. 添加注册和登录页面及逻辑 |
| 添加故事评论功能 |
1. 生成
Comment
模型;2. 运行迁移;3. 关联评论模型;4. 添加评论表单和列表
|
| 添加投票限制功能 | 1. 添加唯一约束;2. 添加投票检查逻辑 |
超级会员免费看
30

被折叠的 条评论
为什么被折叠?



