15

可能重复:
Ruby on Rails:在模型中验证还是在数据库中验证更好?

我看到可以在 Rails 模型和迁移中添加相同的约束/验证。但是哪一个是最好的方法?在模型和数据库级别(以及为什么)进行验证是一种好习惯吗?或者他们在rails中相同?

例如,我们可以在模型和迁移中对名称进行相同的验证

class User < ActiveRecord::Base
  validates :name, :uniqueness => true, :presence => true
end

class CreateUser < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :name, :unique => true, :null => false
    end
  end
end
4

1 回答 1

29

尽可能在数据库级别和模型级别进行验证。

为什么?对于初学者,活动记录不会在所有上下文中强制验证。以下方法跳过验证,并将对象保存到数据库中而不管其有效性:

decrement!
decrement_counter
increment!
increment_counter
toggle!
touch
update_all
update_attribute
update_column
update_counters

如果你传递:validate => falsesave,它也会跳过验证。有关详细信息,请参阅跳过验证的Active Record 验证和回调指南部分。(如果这让您担心,甚至还有禁用这些方法的宝石。)

所以原因 #1是 Rails 验证无论如何都不是完全证明的:完全依赖它们是有风险的,特别是对于任务关键型验证,例如唯一性。

说到这一点,原因 #2(我想不通):activerecord 验证容易出现竞争条件,尤其是 Rails 的唯一性验证器不能保证唯一性。这是众多文章中的一篇,它记录了为什么会这样。

尽管它们可能很少发生,但违反唯一性约束可能会破坏整个数据集。在 Rails 即将执行此操作的极少数情况下,您希望不惜一切代价阻止它,这就是 DB 唯一性约束的用武之地:数据库是为处理这种情况而构建的,并且会始终如一地强制执行唯一性,即使 Rails 没有这样做。

原因 #3:为什么不在模型和数据库中都进行验证?当然,你会重复一些,但与 Rails 错过唯一性验证检查之类的东西相比,这通常是一个非常小的问题。这真的不是一个非此即彼的命题:在数据库中尽可能地重复验证总是更好,特别是对于任务关键型约束,例如唯一性。

无论如何,这些是我的想法,希望对您有所帮助。

参考:强制正确性的地方(Gary Bernhardt 的截屏视频,需要订阅才能查看)

于 2012-10-29T14:13:54.613 回答