首页 > 解决方案 > 在 ActiveModel::EachValidator 中使用实例变量

问题描述

我遇到了(对我来说)关于使用每个验证器的奇怪事实。例如,我们有一些自定义的 each 验证器和一些模型:

class Thing < ApplicationRecord
  validates :field, custom: true
end

class CustomValidator < ActiveModel::EachValidator
  def validate_each(record, _attribute, _value)
    @record = record
  end
end

我发现当我们第一次调用 Thing 模型时,会创建一次 CustomValidator 类的实例。这意味着我们将为每个 Thing 实例拥有相同的验证器对象。我的问题是:你怎么看,我们能不能像这样在验证器中使用实例变量......因为看起来验证器对象只会被创建一次,例如,如果我们调用 Thing.first.valid?然后是 Thing.last.valid?@record 在我们重新分配之前将具有相同的值。

或者可能会为每个客户端创建一个单独的验证器对象?

我只是担心当同时验证多个小部件时,我们是否有可能面临围绕 @record 变量的竞争?

谢谢

标签: ruby-on-railsrubyvalidationrace-condition

解决方案


我找到了另一种方法,只用一个类方法“validate”和一个实例方法“validate”来定义类,并像块一样使用这个类方法。因此,我们可以在类中移动大量验证,在模型事物中使用它,并在验证器方法之间使用实例变量

class Thing < ApplicationRecord
  validate MyCustomValidator
end

class MyCustomValidator
  def self.validate(record)
    new(record).validate
  end

  def initialize(record)
    @record = record
  end

  def validate
    # some payload with @record
    validate_breakdowns
    validate_indicators
  end

  private

  attr_reader :record

  def validate_breakdowns
    # some payload with @record
  end

  def validate_indicators
    # some payload with @record
  end
end

推荐阅读