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
修改后,运行测试,正常。说明我们的修改没有破坏什么。但是我们要确保的是不仅现在能工作,而且进一步修改后也能正常。以后我们需要功能测试,现在我们做下单元测试。
相关推荐
如何启动一个新的Rails应用程序? Craft的设计系统 了解MVC(模型-视图-控制器)体系结构 模型:Active Record迁移,验证,回调,关联和查询接口 视图:布局,部分和表单助手 控制器:动作,强参数 Rails路由 ...
最近因为工作的需要,准备安装ruby on rails,在网上搜了下,步骤都类似,但实际安装过程中却碰到很多问题。 说明下:文章是按照我尝试的过程描述的。但最终是靠 运行 railsinstaller一键式安装包才成功的(第五段)...
完整的Ruby on Rails开发人员课程第2节:Ruby编程语言31:身份验证器项目37:区号字典44:最终的Ruby项目:类,模块,Mixins 1-bcrypt 46:最终的Ruby项目:类,模块,Mixins 2-方法48:最终的Ruby项目:类,模块,...
一个自托管的工具,用于监视Ruby on Rails应用程序的性能。 这是New Relic APM,Datadog或其他类似服务的简单免费替代品。 它允许您跟踪: 吞吐量报告(请参阅RPM数量(每分钟的请求数)) 平均响应时间 最慢的...
这个 gem 将包装在 Rails 资产管道的热情拥抱中。 Rails 3.1 及更高版本。 这包括 最新版本的backbone-forms (0.10.0) 骨干引导模式库 骨干验证库 (0.7.1) 第 1 步:将它添加到您的 gemfile: gem 'backbone-...
示例 Grape on Rails 应用程序 这是来自的 Grape on Rails 教程的源代码。 第 1 部分:初始设置 第 2 部分:基于令牌的身份验证
ilia Milia是Ruby on Rails应用程序的多租户瑰宝。 Milia支持Devise。 您正在查看将miilia与Rails 5.x应用程序一起使用的文档。 如果要使用Rails 4.2.x,请切换到。介绍Milia是(SaaS)应用程序的可靠选择,该应用...
点击展开本周,我们将静态网站转换为Ruby on Rails应用程序。 第一步是使用Assett Pipeline提供运行网站所需的JS,CSS和HTML文件。 我们在HTML代码中实现了嵌入式Ruby语法。 我们创建了一个包含多个表的数据库: ...
LoveLexicon是一个受UrbanDictionary启发的Web应用程序,该应用程序是使用Ruby on Rails和React.js构建的。 发现有关关系问题的专家定义! LoveLexicon允许用户: 创建一个帐户来发布单词/定义 登录/注销 创建,...
该站点的第一个版本是作为一个项目构建的,截止日期为十天。 将添加更多功能,未来将进一步深化和扩展现有功能。 特征 使用 BCrypt 保护前端和后端用户身份验证 交互式路线图,用户可以在其中创建和保存路线 路线...
第22章 案例研究——基于Ruby on Rails架构的抵押贷款计算器 附录A 习题参考答案 附录B XPath参考 附录C XSLT参考 附录D XML文档对象模型 附录E XML Schema元素与属性参考手册 附录F XML Schema数据类型 附录G SAX ...
国内知名的高端IT技术作家,已出版《Spring 2.0宝典》、《基于J2EE的Ajax宝典》、《轻量级J2EE企业应用实战》、《Struts 2权威指南》、《Ruby On Rails敏捷开发最佳实践》等著作。 目录: 第0章 学习Java...
它建立在 Backbone 和 Ruby on Rails 之上。 用户可以: 创建帐户 创建会话(登录) 创建电视节目架 将电视节目添加到书架 按标题搜索电视节目 查看电视节目信息 添加朋友 评价和评论电视节目 评论评论 ...
第一次,许多人可以使用不同的语言进行交流,每个人都将自动看到所有以他们自己的语言翻译的消息。 由JD Bean和Jeremy Gottfried开发。 该项目未维护,目前不寻求贡献。 动机 今天,我们可以实时向世界各地的人们...
火箭电梯信息系统点击展开本周,我们将静态网站转换为Ruby on Rails应用程序。 第一步是使用Assett Pipeline提供运行网站所需的JS,CSS和HTML文件。 我们在HTML代码中实现了嵌入式Ruby语法。 我们创建了一个包含多个...
为此,我们尝试将我们在其他 Web 框架中看到的最好的东西结合起来,包括用其他语言实现的框架,例如 Ruby on Rails、ASP.NET MVC 和 Sinatra。 Laravel 易于访问,但功能强大,为大型、健壮的应用程序提供了强大的...
这是Ruby on Rails框架的第一个介绍。 该网站必须处于允许您创建一个新部分的状态,该部分可以保存以采购订单的形式计算估算值的Javascript形式。 此采购订单包括估算表单的关键元素,并允许您输入更多详细信息。 ...
为此,我们尝试将我们在其他 Web 框架中看到的最好的东西结合起来,包括用其他语言实现的框架,例如 Ruby on Rails、ASP.NET MVC 和 Sinatra。 Laravel 易于访问,但功能强大,为大型、健壮的应用程序提供了强大的...
这是对Go的原始QOR的完全重写,它是用Ruby on Rails编写并在内部使用的专有框架。 QOR 1.0是第一个以MIT许可证开源和分发的版本。 什么不是QOR QOR不是“盒装交钥匙解决方案”。 您需要适当的编码技巧才能使用它。...