ruby-on-rails 对不同的属性使用相同的验证器Rails

icnyk63a  于 2023-01-10  发布在  Ruby
关注(0)|答案(2)|浏览(220)

我有一个定制的验证器,我想将它应用于同一个模型中的多个属性
现在我下面的作品就好了:

validates :first_name, validator_name: true
 validates :age, validator_name: true
 validates :gender, validator_name: true

但当我尝试时:

validates :first_name, :age, :gender, validator_name: true

验证器将为第一个属性(:first_name)运行,但其他属性不运行。这有可能实现吗?我花了几个小时在谷歌上搜索,但没有找到任何示例

module Person
  class SomeValidator < ActiveModel::EachValidator

    def validate_each(record, attribute, value)
      return unless can_do_something?(record, attribute)

      #... more code 
    end

   def can_do_something?(record, attribute)
      anything_new = record.new_record? || record.attribute_changed?(attribute)
   end
  end
end
ltskdhd1

ltskdhd11#

不确定这应该只是一个评论还是构成了回答;不管你的要求是什么。
我有一个定制的验证器,我想将它应用于同一个模型中的多个属性
......是EachValidator的工作原理。
所以你所描述的...
验证器将为第一个属性(:first_name)运行,但不为其他属性运行。
..不可能准确。
例如:

require 'active_model'
class StartsWithXValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    unless value.match?(/^(?:\d+\s|^)X/)
      record.errors.add attribute, "must start with X"
    end
  end
end

class Person
  include ActiveModel::Model
  include ActiveModel::Validations
  
  attr_accessor :name, :city, :street
  
  validates :name, :city, :street, starts_with_x: true
end

在这种情况下,将通过StartsWithXValidator确认所有三个属性。
例如:

person = Person.new({name: 'Xavier', city: 'Xenia', street: '123 Xenial St'})
person.valid? 
#=> true

person_2 = Person.new({name: 'Benjamin', city: 'Philadelphia', street: '700 Market St'})
person_2.valid? 
#=> false
person_2.errors.full_messages 
#=> ["Name must start with X", "City must start with X", "Street must start with X"]

工作示例

flseospp

flseospp2#

我认为您可以使用自定义方法验证:

validate :validate_person

  def validate_person
    [:first_name, :age, :gender].each do |attr|
      validates attr, validator_name: true
    end
  end

Reference: https://guides.rubyonrails.org/active_record_validations.html#custom-methods

相关问题