'Custom validator with argument
I have the following class:
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
This particular validation happens to act on value('Transaction'). I'd like my validator to be sufficiently generic that I can pass in any value (e.g. value('Date of birth')) and have it act on that value.
How can I accomplish this?
Solution 1:[1]
This is an old question, but I think this is more in the ballpark of what you were asking.
ActiveModel::EachValidator allows you to pass in options as a hash, which will be available in the class instance with options.
You can set up the validation in your model like
class SomeModel < ApplicationRecord
validates :transaction, date_format: { value: 'Transaction' }
end
And the custom validator would look like:
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
Solution 2:[2]
But presumably you want the validations to run unconditionally, so...
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
This can be extracted to an each_validator as per Marek Lipka's answer, with a custom constant DATES_TO_VALIDATE for each model and access it in the validator as model.class::DATES_TO_VALIDATE
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | brainbag |
| Solution 2 | SteveTurczyn |
