rails更新时的唯一性验证

rob*_*ert 3 ruby-on-rails ruby-on-rails-3

我在其中一个模型上有以下验证规则,

validates :reciept_num, :presence => true,
                        :numericality => { :only_integer => true },
                        :uniqueness => true,
                        :on => :update,
                        :if => "!status_id.nil?"`
Run Code Online (Sandbox Code Playgroud)

现在,当我使用update_attributes方法更新对象时,它会给我以下错误

reciept_num: has already been taken.

在更新对象时,我没有更改reciept_num属性?那么,为什么这个验证在更新时失败了?

如果我没有更新值,它必须是旧的,因此应该通过验证.我错过了什么.

Fre*_*ung 5

首先,验证不会根据属性是否已更改而运行(当然,除非您明确要求验证).每次有唯一性验证记录保存和验证可运行(通过定义:on,:if,:unless选项),它会检查是否有自身以外的任何情况下,与被认为是独特的价值.

由于你的验证有条件,我想你最终可能会创建两个具有相同收据num的实例,但两者都有一个null status_id.将status_id列和验证设置为操作并查找其他实例.

另一件事是,由于您的验证只在更新时,您可以创建具有相同收据num的多个实例,再次尝试更新记录将触发验证.

我只是猜测精确的场景.

  • 要详细说明Mu的评论,这里是'validates_uniqueness_of'的文档.请特别注意"并发和完整性"部分,其中讨论了应用级验证何时崩溃:http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html#method-i-validates_uniqueness_of (3认同)