Active Record 数据验证
数据验证概览
为什么要做数据验证
数据验证确保只有有效的数据才能存入数据库,在模型中做验证是最有保障的,只有通过验证的数据才能存入数据库。数据验证和使用的数据库种类无关,终端用户也无法跳过,而且容易测试和维护。
数据验证的方式主要有数据库原生约束、客户端验证和控制器层验证:
数据库约束无法兼容多种数据库,难以测试和维护,但是如果其他应用也要使用这个数据库,最好能够在数据库层做一些约束。
客户端验证可靠性不高,但是和其他验证方式结合可以提供实时反馈
控制器层验证不灵便,难以测试和维护,只要可能就应该保证控制器的代码简洁,这样才有利于长远发展
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
检查表单提交时,用户界面中的复选框是否被选中,一般用来要求用户接受应用的服务条款、确保用户阅读了一些文本等。
class Person < ApplicationRecordvalidates :terms_of_service, acceptance: true
end
复制代码
validates_associated
如果模型与其他模型有关联,而且关联的模型也需要验证,就是用这个方法,保存对象时,会在相关联的每个对象上调用 valid?
方法。
class Library < ApplicationRecord has_many :booksvalidates_associated :books
end
复制代码
不要在关联的两端使用,这样会造成无限的循环
confirmation
检查两个文本字段的值是否完全相同,如确认邮件地址或者密码。这个验证创建一个虚拟属性,其名字为要验证的属性名后加 _confirmation
。
class Person < ApplicationRecordvalidates :email, confirmation: true
end
复制代码
在视图模板中视图可以如下:
<%= text_field :person, :email %>
<%= text_field :person, :email_confirmation %>
复制代码
因为只有在 email_confirmation
值不是 nil
时才会验证,所以需要添加存在性验证
class Person < ApplicationRecordvalidates :email, confirmation: truevalidates :email_confirmation, presence: true
end
复制代码
使用 :case_sensitive
选项可以说明是否区分大小写,这个选项默认值是true
class Person < ApplicationRecordvalidates :email, confirmation: {case_sensitive: false}
end
复制代码
exclusion
这个方法检查属性的值是否不在指定的集合中,集合可以是任何一种可枚举的对象
class Account < Applicationvalidates :subdomain, exclusion: {in: %w(www us ca jp), message: "%{value} is reserved"}
end
复制代码
in
选项设置哪些值不能作为属性的值,in
的别名是 with
formate
这个方法检查属性的值是否匹配 :with
选项指定的正则表达式。
class Product < ApplicationReocrdvalidates :legacy_code, formate: {with: /\A[a-zA-Z]+\z/, message: "only allows letters"}
end
复制代码
inclusion
这个方法检查属性的值是否在指定的集合中,集合可以是任何一种可枚举的对象
class Coffee < ApplicationRecordvalidates :size, inclusion: {in: %w(small mediun large), message: "%{value} is not a valid size"}
end
复制代码
length
这个方法验证属性值的长度,有多个选项
class Person < ApplicationRecordvalidates :name, length: {minimum: 2}validates :bio, length: {maximum: 500}validates :password, length: {in: 6..20}validates :registration_number, length:{is: 6}
end
复制代码
可用的长度约束选项有:
:minimum
:最短长度:maximum
:最长长度:in
或者:within
:长度范围:is
:等于该长度
定制错误消息可以使用 :wrong_length
、:too_long
、:too_short
选项,%{count}
表示长度限制的值
class Person < ApplicationRecordvalidates :bio, length: {maximum: 1000, too_long: "%{count} characters is the maximum allowed"}
end
复制代码
numericality
检查属性是否只包含数字,默认匹配的值是可选的正负符号后加整数或浮点数,如果只接受整数,把 :only_integer
选项设置为 true
,否则会使用Float把值转换为数字。
class Player < ApplicationRecordvalidates :points, numericality: truevalidates :games_played< numericality: {only_integer: true}
end
复制代码
除此之外,这个方法还可指定以下选项:
: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
或空字符串
class Person < ApplicationRecordvalidates :name, :login, :email, presence: true
end
复制代码
absence
验证属性值是否为空,使用 present?
方法检查是否为 nil
或空字符串
class Person < ApplicationRecordvalidates :name, :login, :email, absence: true
end
复制代码
uniqueness
这个方法在保存对象前验证属性值是否唯一,这个方法不会在数据库中创建唯一性约束,所以有可能两次数据库连接创建的记录具有相同的值,所以最好在数据库字段上建立唯一性约束。
class Account < ApplicationRecordvalidates :email, uniqueness: true
end
复制代码
这个验证会在模型对应的表中执行一个 SQL 查询,检查现有的记录中该字段是否已经出现过相同的值。
可以使用 :case_sensitive
选项
class Person < ApplicationRecordvalidates :name, uniqueness: {case_sensitive: false}
end
复制代码
validates_with
这个方法把记录交给其他类做验证。
class GoodnessValidator < ActiveModel::Validatordef validate(record)if record.first_name == "Evil"record.errors[:base] << "This person is evil"endend
endclass Person < ApplicationRecordvalidates_with GoodnessValidator
end
复制代码
这个方法的参数是一个类或者一组类。
validates_each
这个方法使用代码块中的代码验证属性,需要在代码块中定义验证方式。
class Person < ApplicationRecordvalidates_each :name, :surname do |record, attr, value|record.errors.add(attr, 'must start with upper case') if value =~/\A[[:lower:]]/end
end
复制代码
代码块的参数是记录、属性名和属性值。
常用验证选项
:allow_nil
允许 nil
值,如果要验证的值是 nil
就跳过验证
class Coffee < ApplicationRecordvalidates :size, inclusion: {in: %w(small medium large), message: "%{value} is not a valid size"}, allow_nil: true
end
复制代码
:allow_blank
与上面方法类似,使用 blank?
方法判断,空字符串和nil时跳过验证
:message
添加错误消息,消息中可以包含 %{value}
、 %{attribute}
、%{model}
:on
指定验证时机,默认都在保存时验证,使用使用
on: :create
:只在创建时验证on: :update
:只在更新时验证
class Person < ApplicationRecord# 更新时允许电子邮件地址重复validates :email, uniqueness: true, on: :create# 创建记录时允许年龄不是数字validates :age, numericality: true, on: :update# 默认行为(创建和更新时都验证)validates :name, presence: true
end
复制代码
:strict
使用严格验证模式,对象无效时抛出异常
class Person < ApplicationRecordvalidates :name, presence: { strict: true }
endPerson.new.valid? # => ActiveModel::StrictValidationFailed: Name can't be blank复制代码
条件验证
使用 :if
和 :unless
选项只有满足特定条件才验证,值可以是符号、字符串、Proc或数组。 选项为符号时,表示验证之前执行对应的方法。这是最常用的设置方法。
class Order < ApplicationRecordvalidates :card_number
end
复制代码
自定义验证
自定义验证类继承自 ActiveModel::Validator,必须实现validate方法,参数是要验证的记录
class MyValidator < ActiveModel::Validatordef validate(record)unless record.name.starts_with? 'X'record.errors[:name] << 'Need a name starting with X please!'endend
endclass Personinclude ActiveModel::Validationsvalidates_with MyValidator
end
复制代码
验证错误处理
ActiveModel::Errors
的实例包含所有的错误,键是每个属性的名称,只是一个数组,包含错误消息字符串。
errors[]
用于获取某个属性上的错误消息
errors.add
用于手动添加某属性的错误消息,参数是属性和错误消息
errors.details
返回错误详情
errors.clear
清楚errors集合中的所有消息
errors.size
返回错误消息总数。
Active Record 数据验证相关推荐
- Active Record Query Interface 数据查询接口(界面) 看到第8节。
http://guides.rubyonrails.org/active_record_querying.html ✅How to find records using a variety of me ...
- Active Record
class Data extends CI_Controller {function index(){echo 'Hwllo DBer';}//多结果标准查询(对象形式)function select ...
- java ldap操作实例_Java Spring Security示例教程中的2种设置LDAP Active Directory身份验证的方法...
java ldap操作实例 LDAP身份验证是世界上最流行的企业应用程序身份验证机制之一,而Active Directory (Microsoft为Windows提供的LDAP实现)是另一种广泛使用的 ...
- Java Spring Security示例教程中的2种设置LDAP Active Directory身份验证的方法
LDAP身份验证是全球范围内最流行的企业应用程序身份验证机制之一,而Active Directory (Microsoft针对Windows的LDAP实现)是另一种广泛使用的LDAP服务器. 在许多项 ...
- php activerecord,Yii2 优雅的 Active Record
这篇文章我们来看看在 Yii2 之中的 Active Record,为啥要将 Active Record 单独出来说呢?因为个人认为这是 Yii(不管是 Yii1.1 还是 Yii2)最强大的一部分功 ...
- Android开源库--ActiveAndroid(active record模式的ORM数据库框架)
Github地址:https://github.com/pardom/ActiveAndroid 前言 我一般在Android开发中,几乎用不到SQLlite,因为一些小数据就直接使用Preferen ...
- DAL、DAO、ORM、Active Record讲解
目录 模型(Model) 持久层(Persistence) DAL(Data Access Layer,数据访问层) DAO(Data Access Object,数据访问对象) ORM(Object ...
- excel 中vb组合框_Excel表中的数据验证组合框
excel 中vb组合框 There are instructions on my Contextures website for using a combo box with data valida ...
- Spring Boot 框架学习笔记(二)(配置文件与数据注入 yaml基本语法 JSR303数据验证 多环境切换 )
Spring Boot 框架学习笔记(二) 六.appliaction.properties配置与数据注入 6.1 `@Value`注解 测试注入数据 读取输入流 6.2 读取配置文件数据注入 单文件 ...
最新文章
- python画图程序-编程入门06:Python海龟绘图
- Go Iris 中间件
- python对象没有属性_Python-对象没有属性E
- Spring MVC集成slf4j-logback
- LeetCode 1825. 求出 MK 平均值(set + queue)
- 实现自适应位置--footer紧贴浏览器底部
- Spring中的InitializingBean接口
- sql取最大值的那一行_SQL高级功能
- aboutsqlserver.com:mvp
- Gigapixel AI 6.0 for Mac(图片无损放大软件)
- Stencil Buffer(模板缓冲区)
- 啦啦外卖独立版七牛云配置失败解决方案
- ToStringBuilder.reflectionToString用法
- html简单网页源代码表格,HTML 表格
- window.crypto.subtle进行rsa-oaep加密
- Java生成bmp图片_利用24位BMP图实现信息隐写(java语言)
- python爬取淘宝数据魔方_看我是怎么使用淘宝数据魔方--巧用数据魔方把握市场信息...
- 笑声的音效素材,几百个你想要的都在这
- 你越来越孤独的3个原因
- 图解FDISK与FORMAT命令分区与格式化
热门文章
- linux下source命令使用详解
- C++ vector的初始化、添加、遍历、插入、删除、查找、排序、释放操作
- CentOS 7.6 安装 Mysql8.0.17 rpm-bundle.tar解包 rpm安装(个人未验证)
- c++一个问题:while(!cin) 的解释
- 5-简单选择排序C实现(递增递减的简单转换)
- 矩阵A对任意的可逆矩阵p都有Ap=pA,证明A为数量矩阵
- java 调 cmd 没反应
- eclipse如何部署到tomcat上的
- Identityserver4中ResourceOwnerPassword 模式获取refreshtoken
- Poj - 3254 Corn Fields (状压DP)(入门)