我有以下类:
class PatientPaymentSpreadsheetRow < ApplicationSpreadsheetRow
include ActiveModel::Validations
validate :date_format
def date_format
unless value('Transaction').split('/').last.length == 4
errors.add('Transaction', 'date format invalid')
end
end
end
这种特殊的验证恰好作用于value('Transaction')
。我希望我的验证器足够通用,可以传入任何值(例如value('Date of birth')
(,并让它对该值进行操作。
我怎样才能做到这一点?
这是一个老问题,但我认为这更符合您的要求。
ActiveModel::EachValidator
允许您将options
作为散列传递,该散列将在具有options
的类实例中可用。
你可以像一样在你的模型中设置验证
class SomeModel < ApplicationRecord
validates :transaction, date_format: { value: 'Transaction' }
end
自定义验证器看起来像:
class DateFormatValidator < ActiveModel::EachValidator
def validate_each(model, attribute, value)
return if options[:value].split('/').last.length == 4
# ^^^^^^^ hash you pass is here
model.errors.add(attribute, 'date format invalid')
end
end
您可以编写自定义的"每个验证器",如指南:中所述
class DateFormatValidator < ActiveModel::EachValidator
def validate_each(model, attribute, value)
return if value.split('/').last.length == 4
model.errors.add(attribute, 'date format invalid')
end
end
并像这样使用:
class MyCustomModel
include ActiveModel::Validations
attr_accessor :my_date_attr
validates :my_date_attr, date_format: true
end
但可能您希望验证无条件运行,所以…
validate :date_format
DATES_TO_VALIDATE = ['Transaction', 'Date of birth', 'Other date']
def date_format
DATES_TO_VALIDATE.each do |key|
unless value(key).split('/').last.length == 4
errors.add(key, 'date format invalid')
end
end
end
根据Marek Lipka的回答,这可以提取为each_validator
,每个模型都有一个自定义常数DATES_TO_VALIDATE
,并在验证器中作为model.class::DATES_TO_VALIDATE
访问它