II 任务B:验证和单元测试
一、迭代B1:验证
到迭代A1止,new product时,如果输入无效价格或者没有输入商品描述,都会把商品添加到数据库中。所以现在需要添加验证。
验证代码应该放到哪里呢?模型层!无论是从数据库中读出,还是写到数据库中,都会先通过模型层。在模型层验证,不用管数据直接来自表单,还是经过程序处理的。
现在模型类的源代码(/app/models/product.rb):
class Product < ActiveRecord::Base end
注:在mac下:ruby 2.0.0p0 (2013-02-24 revision 39474) [x86_64-darwin11.4.0],rails3.2.13 环境。还会生成这样一行:
attr_accessible :description, :image_url, :price, :title
先验证非空的文本字段:
validates :title, :description, :image_url, :presence => true
这里,validates是标准的rails验证器。它会根据一个或者多个条件来验证一个或多个模型字段。
:presence=>true是要验证每个字段都存在,并且内容不为空。也可以写成presence: true,现在这两种写法是一样的意思。按个人习惯保持统一就可以。
现在来看一下效果。点new product进入http://localhost:3000/products/new。不输入任何内容,直接点Create Product按钮,会看到一片红色高亮显示,表示修改生效了。用一行代码就搞定这些了,另外还会注意到,不需要重启程序来测试修改,只要重新加载网页就行。
再来验证一下价格为有效正数:
validates :price, :numericality => {:greater_than_or_equal_to => 0.01}
:numericality验证是否是一个有效的数字;另外还给:greater_than_or_equal_to选项(忒TM长了吧- -)传递一个值0.01(用0.01,不用0;原因是可能输入0.001,而我们价格在数据库中只允许到小数点后两位,结果保存到数据库的数据会是0而不是0.001)。
现在又要确保每个商品有唯一的标题。来添加一个唯一性验证:
validates :title, :uniqueness => true
还要验证图片是否有效:
validates :image_url, :format => { :with=> %r{\.(gif|jpg|png)$}i, :message => 'must be a URL for GIF, JPG, or PNG image.' }
用format选项来实现这个功能。format可以判断字段是否和正则表达式相匹配,这里只检查.gif,.jpg,.png。事实上,我们可能要改变表单,让用户浏览一个可用图片,不过这种情况还是要验证。
现在添加的验证有以下几项内容:
·字段的标题、描述以及图片的URl不是空的
·价格是一个有效的数字,且不少于0.01
·标题在所有的端口中是唯一的。
·图片的URL看起来要是有效的
现在模型的代码如下:
class Product < ActiveRecord::Base validates :title, :description, :image_url, :presence => true validates :price, :numericality => {:greater_than_or_equal_to => 0.01} validates :title, :uniqueness => true validates :image_url, :format => { :with => %r{\.(gif|jpg|png)$}i, :message => 'must be a URL for GIF, JPG, or PNG image.' } end
继续之前再测试一下:
rake test
oh~有两个地方报错了,我们发现一个是在test_should_create_product中,另一个在test_should_update_product中。这就是我们添加的验证导致的,也正是验证的目的,现在测试的创建和更新商品失败了。
E:\works\ruby\depot>rake test SECURITY WARNING: No secret option provided to Rack::Session::Cookie. This poses a security threat. It is strongly recommended that you provide a secret to prevent exploits that may be possible from crafted cookies. This will not be supported in future versions of Rack, and future versions will even invalidate your existing user cookies. Called from: D:/dev/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/ac tionpack-3.2.1/lib/action_dispatch/middleware/session/abstract_store.rb:28:in `i nitialize'. Rack::File headers parameter replaces cache_control after Rack 1.5. Run options: # Running tests: Finished tests in 0.000000s, NaN tests/s, NaN assertions/s. 0 tests, 0 assertions, 0 failures, 0 errors, 0 skips SECURITY WARNING: No secret option provided to Rack::Session::Cookie. This poses a security threat. It is strongly recommended that you provide a secret to prevent exploits that may be possible from crafted cookies. This will not be supported in future versions of Rack, and future versions will even invalidate your existing user cookies. Called from: D:/dev/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/ac tionpack-3.2.1/lib/action_dispatch/middleware/session/abstract_store.rb:28:in `i nitialize'. Rack::File headers parameter replaces cache_control after Rack 1.5. Run options: # Running tests: F.....F Finished tests in 0.796875s, 8.7843 tests/s, 11.2941 assertions/s. 1) Failure: test_should_create_product(ProductsControllerTest) [E:/works/ruby/depot/test/fun ctional/products_controller_test.rb:20]: "Product.count" didn't change by 1. <3> expected but was <2>. 2) Failure: test_should_update_product(ProductsControllerTest) [E:/works/ruby/depot/test/fun ctional/products_controller_test.rb:39]: Expected response to be a <:redirect>, but was <200> 7 tests, 9 assertions, 2 failures, 0 errors, 0 skips
解决办法是在/test/functional/products_controller_test.rb中给出有效的测试数据(下的源代码中这个文件在test/controllers/目录下),修改后的代码:
require 'test_helper' class ProductsControllerTest < ActionController::TestCase setup do @product = products(:one) @update = { title: 'Lorem Ipsum', description: 'Wibbles are fun!', image_url: 'lorem.jpg', price: 19.95 } end test "should get index" do get :index assert_response :success assert_not_nil assigns(:products) end test "should get new" do get :new assert_response :success end test "should create product" do assert_difference('Product.count') do post :create, product: @update end assert_redirected_to product_path(assigns(:product)) end test "should show product" do get :show, id: @product assert_response :success end test "should get edit" do get :edit, id: @product assert_response :success end test "should update product" do put :update, id: @product, product: @update assert_redirected_to product_path(assigns(:product)) end test "should destroy product" do assert_difference('Product.count', -1) do delete :destroy, id: @product end assert_redirected_to products_path end end
修改后,运行测试,正常。说明我们的修改没有破坏什么。但是我们要确保的是不仅现在能工作,而且进一步修改后也能正常。以后我们需要功能测试,现在我们做下单元测试。
相关推荐
- **周二**:创建第一个应用程序,学习如何处理文件、生成器和脚本。 - **周三**:掌握迁移、ActiveRecord、ActionController和ActionView的基本用法。 - **周四**:深入了解ActiveRecord的关联、验证和回调机制;...
### Ruby on Rails Guides v2 - Ruby on Rails 4.2.5 #### 一、重要概念及基础假设 - **重要概念**:本指南旨在帮助读者深入理解Ruby on Rails(以下简称Rails)4.2.5版本的核心功能与最佳实践。 - **基础假设**:...
- **第一个应用:** 创建完应用后,可以通过编写简单的代码来测试Rails的基本功能。例如,创建一个简单的“Hello, Rails!”页面,用来验证环境配置是否正确。 - **链接页面:** Rails提供了强大的路由机制,用于定义...
### Ruby on Rails 指南 v5.0.1 中文版 #### Rails入门 - **前提条件**:为了能够顺利地开始Rails的学习之旅,读者需要具备一定的Ruby语言基础,并且对Web开发有一定的了解。 - **Rails是什么?**:Rails是一种...
通过对《Ruby on Rails心得_V0.1》的学习,我们可以了解到 Ruby on Rails 不仅提供了一种高效、优雅的方式来构建 Web 应用,还通过其丰富的特性和约定简化了开发流程。对于初学者而言,掌握好环境搭建的基础知识是...
- **创建第一个 Rails 应用**:使用命令 `rails new myapp` 可以快速创建一个新的 Rails 应用程序,其中 `myapp` 是应用的名称。 - **启动服务器**:进入应用目录后,通过命令 `rails server` 启动服务器。访问 `...
此外,还会讲解如何创建第一个Rails应用,包括项目结构和基础配置。 ### 第2章:理解Rails 本章将深入探讨Rails的设计理念和核心组件,例如MVC(Model-View-Controller)架构模式的应用。读者将了解到Rails如何...
Ruby on Rails是一个基于Ruby语言的开源Web开发框架,它遵循模型-视图-控制器(MVC)架构模式,旨在提高开发效率和代码可读性。Rails的安装过程是每个想要涉足这个领域的开发者都需要掌握的基础知识。下面将详细介绍...
Ruby on Rails(简称Rails)是一种基于Ruby编程语言的开源Web应用程序框架,它遵循MVC(模型-视图-控制器)架构模式,旨在提高开发效率和代码的可读性。本实践指南将深入探讨Rails的核心概念、关键特性以及如何在...
Ruby on Rails(RoR)是一个开源的Web应用框架,它遵循MVC(模型-视图-控制器)架构模式,以Ruby编程语言为基础,为开发者提供了高效且简洁的开发体验。 本项目的核心知识点包括: 1. **Ruby语言基础**:Ruby是一...
《Ruby on Rails企业应用程序开发》是一本面向专业开发者和对企业级应用有需求的读者的经典教程。这本书详尽地探讨了如何使用Ruby on Rails框架来构建高效、可扩展且可靠的大型企业级应用程序。Ruby on Rails(简称...
《Ruby on Rails的秘密》是一份关于Ruby on Rails框架的高级介绍资料,由该框架的创始人David Heinemeier Hansson编写。这份资料深入探讨了Rails的核心理念和技术细节,旨在为开发者提供一个全面而深入的理解。自...
10. **Gem包管理**:Ruby的Gem生态系统丰富,Rails项目通常依赖于大量第三方Gem,如Devise(身份验证)、CanCanCan(授权)、Carrierwave(文件上传)等,通过Gemfile管理这些依赖。 11. **Asset Pipeline**:Rails...
这篇教程可能涵盖了如何设置开发环境、创建第一个Rails应用程序、理解路由工作原理、搭建数据库模型以及使用ActiveRecord进行数据库操作等内容。 通过阅读《Ruby on Rails.pdf》这份文档,你将学习到: 1. **安装...
Ruby on Rails(简称Rails)是一款基于Ruby语言的开源Web应用程序框架,遵循MVC(Model-View-Controller)架构模式,为开发人员提供了快速开发、简洁代码以及强大的数据库支持。 首先,让我们深入了解Ruby on Rails...
Rails是一个基于Ruby语言的开源Web应用程序框架,它遵循模型-视图-控制器(MVC)架构模式,旨在提高开发效率和代码的可读性。 在这个API文档中,你可以找到关于以下关键知识点的详细信息: 1. **Ruby语法基础**:...
Ruby on Rails,简称Rails,是基于Ruby语言的一个开源Web应用框架,它遵循MVC(Model-View-Controller)架构模式,旨在提升开发效率和代码可读性,鼓励使用敏捷开发方法。这个压缩包包含了“Ruby on Rails敏捷开发...
- `Category.first`:返回第一个记录。 - `Category.last`:返回最后一个记录。 - `Category.all`:返回所有记录。 - `Category.find(1)`:根据主键查找记录。 - `Category.find([1, 3])`:根据多个主键查找...