[Rails] Active Record Validation
资料来源:Rails Guide
Guide
-作用:在数据存入数据库之前进行验证
-学会创建你自己定义的独特的验证方法
-未通过验证后产生的错误信息十分重要
1. Why
数据验证能确保只有合法的数据才会存入数据库
数据存入数据库之前的四种验证方法 比较:
-
客户端验证(浏览器验证) 单独使用可靠性不高
如用js实现,用户在浏览器禁用js后很容易跳过验证
客户端验证和其他验证方式结合使用,可以为用户提供实时反馈 - 控制层验证 不灵便,难以测试和维护,需要保证控制器代码的简洁
- 模型层验证(推荐) 模型层是和数据库相连的,逻辑符合,代码清晰
-
数据库约束验证 缺点:无法兼容多种数据库,且测试和维护较为困难。
如果其他项目的程序也要使用到该数据库,则最好在数据库层添加约束。
某些约束(如:唯一性验证)通过其他方式实现起来有点困难。
2. When Validation
Validation 是什么情况下触发的呢?
-(1)SQL INSERT
在创建一个还未被写入数据库中的记录前;
-(2)SQL UPDATE
在更新一个已经存在与数据库中的记录前。
Tip1: 通常使用new_record?
/persisted?
来判断一个记录是否存在在数据库中。小心有一些创建和更新方法会跳过验证步骤直接插入数据,我们需要记住这些特别的方法。
Tip2: 当然简单地使用valid?/invalid?
或是create/save/update
方法来触发验证器。
Tip3: 值得一提的是save(:validate: false)
可以跳过验证,使用时要注意。
Tip4: 另外要注意的是create
返回的是对象,update/save
返回的是真假。
3. Skip Validation
decrement!, decrement_counter, increment!, increment_counter, toggle!, touch
update_all, update_attribute, update_column, update_columns, update_counters
save(validate: false)
4. Validation Helpers
acceptance, validates_associated, confirmation, exclusion, format, inclusion
length, numericality, presence, absence, uniqueness, validates_with, validates_each
Tips: uniqueness 在验证唯一性的时候要注意他所做的只是在数据插入或跟新到数据库之前查看数据库中是否已经存在。他不能保证你数据库中已经存在的数据确实是唯一的,或者两个数据库连接同时写数据产生不唯一的可能。要达到这个目标我们需要在数据库层也定义唯一性规则。
5. Validation Options
allow_nil, allow_blank, message, on
6. Strict Validations
正常情况下验证一旦出错,会把出错信息存放在error
对象中
通过使用严格的验证,我们得到的是抛出的异常而不是出错信息
异常默认情况下为ActiveModel::StrictValidationFailed
,当然你也可以自定义
validates :name, presence: { strict: true }
validates :token, presence: true, uniqueness: true, strict: TokenGenerationError
7. Conditional Validation
条件验证,当某个条件满足时才进行验证,通过:if, :unless
实现。
# **with_options** 合并相同属性,使用这个方法可以把
# 相同的属性,包括这小条件判断属性合并在一起,简化代码
class User < ApplicationRecord
with_options if: :is_admin? do |admin|
admin.validates :password, length: { minimum: 10 }
admin.validates :email, presence: true
end
end
8. Custom Validation
上面提到的validates_with, validates_each
方法是用于呼叫自定义验证系统:
-(1) 自定义验证类继承自ActiveModel::Validator
并且重写它的validate
方法,这个方法会接收一个被验证的对象,我们可以添加自定义的前提要求,判断条件,并且返回符合情境的错误信息。通过validates_with
方法来使用。
-(2) 自定义验证类继承自ActiveModel::EachValidator
并且重写它的validate_each
方法,这个方法接收三个参数record, attribute, and value
。record
代表被验证的对象;attribute
代表被验证的属性;value
代表被验证的值。
# 另一种简单的方式是直接定义验证方法
class Invoice < ApplicationRecord
validate :not_me, on: :create
private
def not_me
errors.add(:name, "that's my nickname!") if name == "gurugurusa"
end
end
9. Errors
错误信息只在数据验证发生后才会产生相关的错误信息,通常使用valid?
触发。
通过errors
方法返回ActiveModel::Errors
对象,这个错误对象的实例变量messages
是一个哈希,我们通过指定属性的键来找出特定属性的错误信息,是一个数组。
-errors 是错误对象,包含所有错误信息。
-errors[:attr] 可以指定某个属性的错误信息,同 errors.messages[:attr] 。
-errors.add 手动添加某个属性相关的错误信息,后跟着属性名和错误信息。
-errors.messages[:name] << "错误信息",同 errors.add (格式略不同)
-errors.full_messages 将错误信息以用户友好的形式输出,同 errors.to_a
-errors.details 从另一个角度来查看错误信息 (不同的结构形式)
-errors[:base] 显示的错误信息不针对某一个列,通过 add 手动添加。
-errors.size/errors.count 显示错误信息个数。
-errors.clear 清除所有错误信息。
Displaying Validation Errors in Views
使用rails generate scaffold
会生成处理错误信息的表单。