插入与创建时的 Rails 验证

Rails validation on insert vs create

提问人:Neil Middleton 提问时间:9/14/2023 更新时间:9/15/2023 访问量:42

问:

我有一个模型,其中记录的有效性取决于插入时存在哪些其他记录。

虽然情况不完全相同,但假设我有一个 AuctionBid 模型——出价本身是有效的(有用户、价值、货币等等),我希望 Rails 告诉我情况就是这样。

但是,当我将出价插入数据库并发现其他一些记录是较大的出价时,我现在希望该记录无效且不保存。

用:

validates :bid_is_valid, on: :create

并没有完全做到这一点,因为它会验证记录,就好像它正在入一样。如何让验证仅在插入时运行?我是否需要一个或什么东西来停止在验证中插入?before_save

Ruby-on-Rails 验证 ActiveRecord

评论

0赞 mechnicov 9/14/2023
if: :new_record??
2赞 mechnicov 9/14/2023
或者您需要一些数据库层约束来排除竞争条件?问题对我来说似乎不清楚CHECK

答:

0赞 max 9/15/2023 #1

Rails 验证是应用程序端的,在尝试 INSERT 或 UPDATE 查询之前执行。它们只是在某些生命周期事件之前触发的回调,并将错误添加到 errors 对象中,从而阻止保存/更新。

验证实际上并不能保证数据库数据的完整性,并且很容易被规避。它们只是防止无效数据在大多数时候溜走,从而导致无效数据,并向用户提供有关查询问题的反馈。

一个常见的例子是唯一性验证,它非常容易受到竞争条件的影响。

保证数据的实际完整性是在数据库端完成的,但有约束。Rails 6.1 添加了一个方便的check_constraint方法,用于在迁移中添加约束(不使用原始 SQL 字符串)。

class CreateProducts < ActiveRecord::Migration
  def change
    create_table :products do |t|
      t.string :name
      t.integer :price
      t.check_constraint "price_check", "price > 100" 
    end
  end
end

请注意,如果数据的完整性很重要,则需要验证和约束。验证仍将捕获大部分错误输入,并防止其升级为数据库驱动程序错误。