【问题标题】:Using instance variables inside ActiveModel::EachValidator在 ActiveModel::EachValidator 中使用实例变量
【发布时间】:2020-12-08 19:29:58
【问题描述】:

我遇到了(对我而言)关于使用每个验证器的奇怪事实。例如,我们有一些自定义的 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-rails ruby validation race-condition


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-14
    • 2014-03-20
    • 2012-03-28
    • 2010-11-03
    • 1970-01-01
    • 2019-02-01
    • 2016-08-19
    • 2011-10-03
    相关资源
    最近更新 更多