在自定义验证中使用ruby on rails验证助手

问题描述 投票:0回答:2

比方说,我有许多只能具有一组特定字符串值的属性。

通常,我们会看到以下内容。

class User < ApplicationRecord
   validates :foo, inclusion: { in: ['some', 'array'] }
   validates :bar, inclusion: { in: ['another', 'array'] }
   validates :moo, inclusion: { in: ['one_more', 'array'] }
end

我的模型中有很多这类验证,我想将它们干燥。因此,我尝试了以下操作,但出现错误undefined method 'validates' for #User:0x00007fdc10370408

class User < ApplicationRecord
  VALIDATION_ENUMS = {
    foo: %w[foo1 foo2],
    bar: %w[bar1 bar2]
  }.freeze

  validate :validate_enums

  def validate_enums
    VALIDATION_ENUMS.each_key do |attribute|
      validates attribute, inclusion: { in: VALIDATION_ENUMS[attribute] }
    end
  end
end

如何从我的函数中访问ActiveModel :: Validations帮助器方法?

或者还有更好的方法吗?

ruby-on-rails ruby validation helper
2个回答
1
投票

[请记住,validates是一个类方法,仅在加载该类以建立将被验证的内容时执行一次。 validate正在调用实例方法。

更好的方法可能是在加载类时立即执行DRY代码。

class User < ApplicationRecord
 validate_enums = {
    foo: %w[foo1 foo2],
    bar: %w[bar1 bar2]
  }.freeze

   validate_enums.each do |key, array|
     validates key, inclusion: { in: array }
   end

[请注意,由于您不再引用validate_enums,因此无需使其成为类常量,这就是为什么我没有这样做。

但是您实际上并没有节省任何行数并增加了复杂性,所以我自己坚持使用明确的validates


0
投票

这种方法不会成功。验证方法是在编写实例方法时修改类本身的类方法,该实例方法在调用#valid?时将在类的实例上被调用。

如果要向类动态添加现有验证,则需要创建类方法:

class User < ApplicationRecord
  def self.add_inclusion_validations(hash)
    # don't use each_key if you're iterating over both keys and values
    hash.each do |key, values|
      validates_presence_of key, in: values
    end
  end

  add_inclusion_validations(
    foo: %w[foo1 foo2],
    bar: %w[bar1 bar2]
  )
end

当然,您也可以完全跳过该方法:

class User < ApplicationRecord
  {
    foo: %w[foo1 foo2],
    bar: %w[bar1 bar2]
  }.each do |key, values|
      validates_presence_of key, in: values
  end
end

如果您要编写一种使用其他验证的现有功能的验证方法,则可以创建ActiveRecord::ValidatorActiveRecord::EachValidator子类并在此处使用现有的验证。但是,您确实需要从reading the guides和API文档开始,以便对它的工作原理有基本的了解。

© www.soinside.com 2019 - 2024. All rights reserved.