数据验证简介
class Person < ActiveRecord::Base
validates :name, presence: true
end
Person.create(name, "Jeek Wong").valid? #=> true
Person.create(name, nil).valid? #=> false
为何做数据验证
在模型中做数据验证是最有保障的,只有通过验证的数据才能存入数据库。
数据存入数据库之前还有几种:包括数据库内建的约束,客户端验证和控制器层验证。
- 数据库约束和“存储过程”无法兼容多种数据库。
- 客户端验证很有用,单独使用时可靠性不高。
- 控制器层验证很诱人,但一般都不灵活。只要可能,就要保证控制器代码简洁性。
什么时候做数据验证?
在Active Record中对象有两种状态:一种在数据库中有对应的记录,一种没有。新建的对象(例如使用new)这还不属于数据库。
在对象上调用save方法后,才会把对象存入相应的数据表。
Active Record使用实例方法new_record?判断对象是否已经存入数据库。
爆炸方法会在验证失败后抛出异常。
跳过验证
有些方法会跳过验证,不管验证是否通过都会把对象存入数据库。
valid?和invalid?
valid?方法检验对象的合法性。valid?方法会触发验证数据。
Active Record验证结束后,所有发现的错误都可以通过实例方法errors.message获取,该方法返回一个错误集合。
如果数据验证后,这个集合为空,则说明该对象是合法的。
注意:使用new方法初始化对象时,即使不合法也不会报错,因为此时还没做数据验证。
invalid?是valid?的逆测试,会触发数据验证,如果找到错误就返回true,否则返回false。
errors[]
要检查对象某个属性的合法性,可以使用errors[:attribute]。errors[:attrbute]的所有错误。如果该属性没有错误,就返回空数组。
这个方法只在数据验证之后使用,只收集错误信息,并不会触发验证。
数据验证帮助方法
所有帮助方法都可以指定:on和:message选项,指定何时做验证及验证失败后向errors集合添加什么消息。
:on选项的可选值是:create和:update。
acceptance
这个方法检查表单提交时,用户界面中的复选框是否被选中。这种验证只针对网页程序,不会存入数据库(如果没有对应的字段,该方法会创建一个虚拟属性)
validates_assocated
如果模型和其他模型有关联,也要验证有关联的模型对象。保存对象时,会在相关联的每个对象上调用valid?方法。
confirmation
验证两个文本字段的值是否完全相同,这个帮助方法会创建一个虚拟属性,其名字为要验证的属性名后加_confirmation。
exclusion
这个帮助方法检查属性的值是否不再指定的集合中。集合可以是任何一种可枚举的对象。
exclusion方法要指定:in选项,设置哪些值不能作为属性的值。:in选项有个别名叫:with,作用相同。
format
这个帮助方法检查属性的值是否匹配:with选项指定的正则表达式、
inclusion
这个方法帮助检查属性的值是否在指定的集合中。集合可以是任何一种可枚举的对象。这个:in选项有个别名为:within。
length
这个帮助方法验证属性值得长度,有多个选项。
长度的选项有:
:minimum : 属性的值不能比指定的长度短
:maximum : 属性的值不能比指定的长度长
:in (或 :within) : 属性值得长度介于指定值之间。
:is : 属性值得长度必须等于指定值
numericality
这个帮助方法检查属性的值是否包含数字,默认情况下是可选的正负号后加整数或是浮点数。
presence
这个帮助方法检查指定的属性是否为非空值,调用blank?方法检查值是否为nil或是空字符串。
如果要确保关联对象存在,需要测试关联的对象本身是否存在,而不是用来映射关联的外键。
absence
这个方法验证指定的属性值是否为空,使用present?方法检测值是否为nil或空字符串。
uniqueness
这个帮助方法会保存对象之前验证属性值是否唯一。该方法不会再数据库中创建唯一性约束,所以有可能两个数据库连接创建的记录字段的值是相同的。
需要在数据库的字段上建立唯一性索引。
validates_with
这个帮助方法把记录交给其他的类做验证。
validates_each
常用的验证选项
:allow_nil 如果要验证的值为nil就会跳过验证
:allow_blank 如果要验证的值为空,就会跳过验证。
:message 指定的字符串添加到errors集合中
:on 指定什么时候做验证
严格验证
使用严格验证,失败会会抛出ActiveModel::StrictValidationFailed异常。
条件验证
有时只有满足条件时做验证才说得通。条件可以通过:if和:unless选项指定,这两个选项的值可以使Symbol,字符串,Proc或数组。
:if选项指定何时做验证。如果指定何时不做验证,可以使用:unless选项。
指定Symbol
:if和:unless选项的值为Symbol时,表示要在验证之前执行对应的方法。
指定字符串
:if和:unless选项的值是字符串时,但必须是Ruby代码,传入eval方法中执行。当字符串表示的条件非常短时才会使用这种形式。
指定Proc
使用Proc对象可以再行间编写代码,不用定义额外的方法。这种形式最适合用在一行代码能表示的条件上。
条件组合
有时同一个条件会用在多个验证上,这时使用with_options方法:
联合条件
如果某个验证要满足多个条件时,可以使用数组。
自定义验证方式
自定义验证使用的类
自定义的验证类继承至ActiveModel::Validator,必须通过validate方法,传入的参数是要验证的记录,然后验证这个记录是否合法。
自定义的验证类通过validates_with方法调用
处理验证错误
errors
ActiveModel::Errors的实例包含所有的错误。其键是每个属性的名字,值是一个数组,包含错误消息字符串。
errors[ ]
errors[]用来获取某个属性上的错误消息,返回结果由一个该属性所有错误消息字符串组成的数组。
errors.add
add方法可以手动添加某属性的错误消息。使用errors.full_messages或errors.to_a方法最终显示给用户的形式显示错误消息。
errors[:base]
错误消息可以添加到整个对象上,而不是针对某个属性。
errors.clear 清除errors集合中的所有消息错误
errors.size 返回对象上错误消息的总数
在视图中显示验证错误