version Rails 4.1
- 如何去使用内建的Active Record 校验helpers.
- 如何去创建你自己定制化的校验方法.
- 如何在校验的过程中去获取生成的错误信息.
1 Validations Overview 校验概述
class
Person < ActiveRecord::Base
validates
:name
, presence:
true
end
Person.create(name:
"John Doe"
).valid?
# => true
Person.create(name:
nil
).valid?
# => false
|
正如你所看到的, 我们的校验让我们知道, 我们的 Person 没有一个name的特性是无效的. 第二个 Person 将不会被保存到数据库中去.
1.1 Why Use Validations? 为什么要使用校验?
- 数据库的限制条件 和/或者 存储过程使得校验机制与数据库无关,能够使得测试和维护变得更困难。然而, 如果你的数据库被其他的应用所使用, 那么在数据库级别使用一些限制会是一个好方法. 额外地, 数据库级别(database-level)校验能够安全地处理一些东西(类似于在高频率使用的数据表里采用唯一性), 不同地是这些实现起来有点困难.
- 客户端的校验是很有用的, 但如果独自使用时通常不是很可靠. 如果他们是用 JavaScript 来实现的, 他们可能被忽略, 如果 JavaScript 被用户的浏览器禁止. 然而, 如果结合其他的技术, 客户端校验能够以很方便的方式给用户提供及时的反馈, 当他们使用你的站点时.
- 控制器级别(Controller-level)的校验很容易使用, 但常常会使测试和维护变得笨重和困难. 只要有可能, 保持你的控制器精简是个好方法, 使得你的应用能够有一个良好的状态来长时间运行.
1.2 When Does Validation Happen? 校验在什么时候发生呢?
class
Person < ActiveRecord::Base
end
|
我们可以看一下它是如何工作的, 通过 rails console 的输出内容:
$ bin/rails console
>> p = Person.
new
(name:
"John Doe"
)
=>
#<Person id: nil, name: "John Doe", created_at: nil, updated_at: nil>
>> p.new_record?
=>
true
>> p.save
=>
true
>> p.new_record?
=>
false
|
创建和保存一个新的记录将会发送一个 INSERT 的SQL操作给数据库. 更新一个已存在的记录将会发送一个 UPDATE 的SQL操作. 校验通常是在这些命令被发送到数据库之前运行的. 如果任何的校验失败, 那么这个对象将会被标记为无效, 而Active Record 将不会去执行 INSERT 或者 UPDATE 操作. 这就会避免保存一个无效的对象到数据库里. 你可以选择用一个指定的校验来运行, 当一个对象被创建, 保存, 或者更新的时候.
warning: 有许多种方式来改变数据库中的对象状态. 一些方法会触发校验, 但有些就不会. 这也就意味着, 如果你不注意, 很有可能保存对象到数据里时是一个无效的状态.
下面的方法会触发校验, 只有当对象有效时才会把对象保存:
create
create!
save
save!
update
update!
有感叹号的版本(例如, save!)抛出一个异常, 当记录是无效的时候. 没有感叹号的版本则不会, save 和 update 返回 false, create 则会返回一个对象.
1.3 Skipping Validations 跳过的校验
decrement!
decrement_counter
increment!
increment_counter
toggle!
touch
update_all
update_attribute
update_column
update_columns
update_counters
注意, save 也能跳过校验, 如果传入的参数为 validate: false. 这个方法使用的时候也要注意.
save(validate: false)
1.4 valid?
and invalid? 有效? 无效?
class
Person < ActiveRecord::Base
validates
:name
, presence:
true
end
Person.create(name:
"John Doe"
).valid?
# => true
Person.create(name:
nil
).valid?
# => false
|
在 Active Record 已经执行完校验之后, 任何的错误都能通过 errors.messages 实例方法中找到, 它会返回一连串的错误信息. 当然地, 如果运行完校验后这个错误集合是空的, 那么这一个对象是有效的.
注意, 对象是通过 new 来实例化的, 这不会产生错误信息, 即使它理论上是无效的, 因为在使用 new 时, 校验还没有开始执行.
class
Person < ActiveRecord::Base
validates
:name
, presence:
true
end
>> p = Person.
new
# => #<Person id: nil, name: nil>
>> p.errors.messages
# => {}
>> p.valid?
# => false
>> p.errors.messages
# => {name:["can't be blank"]}
>> p = Person.create
# => #<Person id: nil, name: nil>
>> p.errors.messages
# => {name:["can't be blank"]}
>> p.save
# => false
>> p.save!
# => ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
>> Person.create!
# => ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
|
invalid? 就是 valid? 的互逆. 它触发了你的校验, 当在对象中有任何错误信息时, 返回 true, 否则就返回 false.
1.5 errors[] 错误数组
class
Person < ActiveRecord::Base
validates
:name
, presence:
true
end
>> Person.
new
.errors[
:name
].any?
# => false
>> Person.create.errors[
:name
].any?
# => true
|
我们将会进一步地了解校验的错误信息在 Working with Validation Errors 部分. 至于现在, 让我们转到内建的校验 helpers, 这是 Rails 默认提供的.