模型在验证中失败但已创建

时间:2016-04-27 22:31:01

标签: ruby-on-rails ruby activerecord activemodel

我现在面临一个问题很久了。我的代码如下:

class BrokenModel < ActiveRecord::Base
  validates_with BrokenValidator

  has_many :association_name
end

class BrokenValidator < ActiveModel::Validator
  def validate record
    @record = record

    check_alerted
  end

  private

  def check_alerted
    return if @record.association_name.to_a.empty?

    alerted = <test for alerted>
    if alerted
      @record.errors[:base] << "It was alerted recently"
    end

    p "check_alerted: #{@record.errors[:base]}"
  end
end

worker.rb

[...]
BrokenModel.create(association_name: [model1, model2])
[...]

在我最后一次打印的日志中显示验证仅传递了一次,但实际上我为此模型创建了多个条目,并显示association_name

我的环境在多个线程和多个核心中运行它,但由于条目是彼此分开创建的,因此它不是并发问题,除非分离线程中的异常影响模型创建。

出于好奇的缘故,这是在Sidekiq工作中运行。

修改

所以我在日志中注意到它可能是一个并发问题。所以这是正在发生的事情:

  • 实例1验证:最近提醒:失败(最近被提醒)
  • 实例2验证:最近通知:已通过
  • 实例2验证:其他验证:失败(其他验证)
  • 实例2创建错误:最近被提醒+其他验证
  • 实例1创建错误:无

如果ActiveModel :: Validator中存在任何类型的线程不安全,或者其他线程可能会覆盖/共享@record,那么有什么线索吗?

1 个答案:

答案 0 :(得分:2)

向记录添加错误不会使其无效。实际上,在保存之前验证模型时,所有先前的错误(包括您在代码中添加的错误)都将被删除。

在模型中进行此验证...不在工作人员中。

validate :check_alerted

def check_alerted
   return if association_name.to_a.empty?
    alerted = test 
    if <test for alerted> 
      errors.add(:base, "It was alerted recently") 
   end 
end