You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
classMyValidator < ActiveModel::Validatordefvalidate(record)unlessrecord.name.starts_with?'X'record.errors[:name] << 'Need a name starting with X please!'endendendclassPersonincludeActiveModel::Validationsvalidates_withMyValidatorend
数据验证概览
为什么要做数据验证
数据验证确保只有有效的数据才能存入数据库,在模型中做验证是最有保障的,只有通过验证的数据才能存入数据库。数据验证和使用的数据库种类无关,终端用户也无法跳过,而且容易测试和维护。
数据验证的方式主要有数据库原生约束、客户端验证和控制器层验证:
数据库约束无法兼容多种数据库,难以测试和维护,但是如果其他应用也要使用这个数据库,最好能够在数据库层做一些约束。
客户端验证可靠性不高,但是和其他验证方式结合可以提供实时反馈
控制器层验证不灵便,难以测试和维护,只要可能就应该保证控制器的代码简洁,这样才有利于长远发展
Active Record 对象分为两种,一种在数据库中有对应记录,一种没有,新建对象还不属于数据库,只有调用了
save
方法后,才会存入数据库,可以使用new_record?
方法判断是否存入数据库,未存入则返回true
,存入则返回false
新建并保存会执行
SQL INSERT
操作,更新记录会执行SQL UPDATE
操作,一般情况下,数据验证发生在执行这些SQL语句之前,如果验证失败,对象会被标记为无效, Active Record 不会向数据库发送指令。以下方法会触发数据验证:
create
create!
save
save!
update
update!
炸弹方法会在验证失败后抛出异常。
以下方法会跳过验证,不管验证是否通过都会把对象存入数据库:
decrement!
decrement_counter
increment!
increment_counter
toggle!
touch
update_all
update_attribute
update_column
update_columns
update_counters
同时,使用
save
方法时,如果传入validate: false
参数,也会跳过验证。同时,也可以使用
valid?
方法自己执行验证,如果对象上没有错误则返回true
,否则返回false
,invalid?
方法则相反。执行验证之后,错误可以通过实例方法errors.message
获取,这个方法返回一个错误集合,如果为空,则说明对象是有效的。需要注意的是,如果没有验证数据,这个方法返回的也是一个空集合。如果要验证某个属性是否有效,可以使用
errors[:attribute]
,这返回一个包含了所有错误的数组,如果没有错误则返回空数组,这个方法和invalid?
方法不一样,这个方法不会验证整个对象,只会检查某个属性是否有错。可以使用
errors.details[:attribute]
检查到底是哪个验证导致属性无效,这个方法返回一个由散列组成的数组。数据验证的辅助方法
辅助方法可以直接在模型中使用,这些方法提供了常用的验证规则,验证失败就会向对象的
errors
集合中添加一个消息。每个辅助方法都可以接受任意个属性名,所以一行代码可以在多个属性上做同一种验证。
acceptance
检查表单提交时,用户界面中的复选框是否被选中,一般用来要求用户接受应用的服务条款、确保用户阅读了一些文本等。
validates_associated
如果模型与其他模型有关联,而且关联的模型也需要验证,就是用这个方法,保存对象时,会在相关联的每个对象上调用
valid?
方法。不要在关联的两端使用,这样会造成无限的循环
confirmation
检查两个文本字段的值是否完全相同,如确认邮件地址或者密码。这个验证创建一个虚拟属性,其名字为要验证的属性名后加
_confirmation
。在视图模板中视图可以如下:
因为只有在
email_confirmation
值不是nil
时才会验证,所以需要添加存在性验证使用
:case_sensitive
选项可以说明是否区分大小写,这个选项默认值是trueexclusion
这个方法检查属性的值是否不在指定的集合中,集合可以是任何一种可枚举的对象
in
选项设置哪些值不能作为属性的值,in
的别名是with
formate
这个方法检查属性的值是否匹配
:with
选项指定的正则表达式。inclusion
这个方法检查属性的值是否在指定的集合中,集合可以是任何一种可枚举的对象
length
这个方法验证属性值的长度,有多个选项
可用的长度约束选项有:
:minimum
:最短长度:maximum
:最长长度:in
或者:within
:长度范围:is
:等于该长度定制错误消息可以使用
:wrong_length
、:too_long
、:too_short
选项,%{count}
表示长度限制的值numericality
检查属性是否只包含数字,默认匹配的值是可选的正负符号后加整数或浮点数,如果只接受整数,把
:only_integer
选项设置为true
,否则会使用Float把值转换为数字。除此之外,这个方法还可指定以下选项:
:greater_than
:属性值需大于 >:greater_than_or_equal_to
:>=:equal_to
:=:less_than
:<:less_than_or_equal_to
:<=:other_than
:!=:odd
:必须为奇数:even
:必须为偶数此方法默认不接受
nil
值,可以使用allow_nil: true
选项允许接受nil
presence
检查属性是否为非空值,方法调用
blank?
方法检查是否为nil
或空字符串absence
验证属性值是否为空,使用
present?
方法检查是否为nil
或空字符串uniqueness
这个方法在保存对象前验证属性值是否唯一,这个方法不会在数据库中创建唯一性约束,所以有可能两次数据库连接创建的记录具有相同的值,所以最好在数据库字段上建立唯一性约束。
这个验证会在模型对应的表中执行一个 SQL 查询,检查现有的记录中该字段是否已经出现过相同的值。
可以使用
:case_sensitive
选项validates_with
这个方法把记录交给其他类做验证。
这个方法的参数是一个类或者一组类。
validates_each
这个方法使用代码块中的代码验证属性,需要在代码块中定义验证方式。
代码块的参数是记录、属性名和属性值。
常用验证选项
:allow_nil
允许
nil
值,如果要验证的值是nil
就跳过验证:allow_blank
与上面方法类似,使用
blank?
方法判断,空字符串和nil时跳过验证:message
添加错误消息,消息中可以包含
%{value}
、%{attribute}
、%{model}
:on
指定验证时机,默认都在保存时验证,使用使用
on: :create
:只在创建时验证on: :update
:只在更新时验证:strict
使用严格验证模式,对象无效时抛出异常
条件验证
使用
:if
和:unless
选项只有满足特定条件才验证,值可以是符号、字符串、Proc或数组。选项为符号时,表示验证之前执行对应的方法。这是最常用的设置方法。
自定义验证
自定义验证类继承自 ActiveModel::Validator,必须实现validate方法,参数是要验证的记录
验证错误处理
ActiveModel::Errors
的实例包含所有的错误,键是每个属性的名称,只是一个数组,包含错误消息字符串。errors[]
用于获取某个属性上的错误消息errors.add
用于手动添加某属性的错误消息,参数是属性和错误消息errors.details
返回错误详情errors.clear
清楚errors集合中的所有消息errors.size
返回错误消息总数。The text was updated successfully, but these errors were encountered: