`
jiajie0531
  • 浏览: 27307 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Active Record Validations 1 Validations Overview 校验概述

阅读更多

version Rails 4.1

 
Active Record 校验
 
这份教程教你如何去校验对象的状态, 在他们进数据库之前, 使用 Active Record 的校验特征.
 
阅读完这份教程, 你将会知道:
  • 如何去使用内建的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? 为什么要使用校验?

校验是被用来保证, 只有有效的数据才能被保存到你的数据库里. 举个例子来说, 它可能对你的应用程序很重要, 确保每一个用户提供的email 地址和发送地址都是有效的. 模型级别(Model-level)的校验是最好的方式来确保只有有效的数据能被保存到你的数据库里. 他们对于数据库是一无所知的, 不能够被终端用户忽视掉, 很方便的进行测试和维护. Rails 使得他们很方便地使用, 对于平常的需求提供了内建的helpers, 也允许你去创建你自己的校验方法.
 
有一些其他的方式来校验数据, 在它被保存进你的数据库里之前, 包括数据库自身的限制, 客户端的校验,  控制器级别(controller-level)的校验. 这里关于正反两方面的观点总结:
  • 数据库的限制条件 和/或者 存储过程使得校验机制与数据库无关,能够使得测试和维护变得更困难。然而, 如果你的数据库被其他的应用所使用, 那么在数据库级别使用一些限制会是一个好方法. 额外地, 数据库级别(database-level)校验能够安全地处理一些东西(类似于在高频率使用的数据表里采用唯一性), 不同地是这些实现起来有点困难.
  • 客户端的校验是很有用的, 但如果独自使用时通常不是很可靠. 如果他们是用 JavaScript 来实现的, 他们可能被忽略, 如果 JavaScript 被用户的浏览器禁止. 然而, 如果结合其他的技术, 客户端校验能够以很方便的方式给用户提供及时的反馈, 当他们使用你的站点时.
  • 控制器级别(Controller-level)的校验很容易使用, 但常常会使测试和维护变得笨重和困难. 只要有可能, 保持你的控制器精简是个好方法, 使得你的应用能够有一个良好的状态来长时间运行.
在某些特定的情况下选择这些. 这是 Rails 团队的意见, 在大多数情况下模型级别(model-level)的校验是最合适的.
 

1.2 When Does Validation Happen? 校验在什么时候发生呢?

有两种类型的 Active Record 对象: 有些是与你数据库中的行相对应的, 有些则不是. 当你创建一个新的对象时, 例如使用 new 方法, 这个时候对象还不属于数据库的.  一旦你紧接着调用 save, 那么它就会被保存到相应的数据表中了.  Active Record 使用 new_record? 实例方法来确定一个对象是否已经存在于数据库中了. 来看一下下文的这个简单的 Active Record 类的例子:
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? 有效? 无效?

为了验证一个对象是否有效, Rails 使用 valid? 方法. 你也可以在你自己的 valid? 触发校验上使用这个方法, 如果没有错误产生, 那么返回 true, 否则就 false. 正如你在上面所看到的:
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[] 错误数组

为了验证一个对象中的一个特性是否有效, 你可以使用 errors[:attribute]. 它会返回一组这个 :attribute 的所有错误信息. 如果对于这个特性上没有错误信息, 那么返回的是一个空的数组.
 
这个只在校验已经运行的情况下有作用, 因为它只检查错误信息的集合, 而不会触发它自身的校验. 它是和 ActiveRecord::Base#invalid? 方法不一样的, 因为它不会去对于一个对象的整体性做校验. 它只会针对对象的各个特性检查是否有错误发生.
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 默认提供的.

 

 

0
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics