Hi,
I want to validate this:
params: start_date, end_date, expiry_date
-
a start_date must either be before or on the same day as the end_date
-
an end_date must either be after or on the same day as the start_date
-
the expiry_date must be before the start_date
-
all dates must be in the future
-
if one date is present then all dates must be present:
valid:
start is present
end is present
expiry is present
valid:
start is not present
end is not present
expiry is not present
invalid:
start is not present
end is present
expiry is present
Otherwise dates do not need to be present.
I came up with the following:
schema = Dry::Validation.Schema do
configure do
def self.messages
super.merge(
errors: {
dates: 'must be in the future!',
_dates: 'must comply with (expiry < start <= end) !',
}
)
end
end
required(:start_date) { filled? }
required(:end_date) { filled? }
required(:expiry_date) { filled? }
validate(
dates: %i[start_date end_date expiry_date]
) do |start_date, end_date, expiry_date|
today = Date.today
(start_date > today) & (end_date > today) & (expiry_date > today)
end
validate(
_dates: %i[start_date end_date expiry_date]
) do |start, end_date, expiry_date|
(start <= end_date) && (start > expiry_date)
end
end
schema.call(date_params) if date_params.any?
What I am missing now is a way to provide error messages for each individual intrusion
e.g.
dates must not be in the past!
expiry_date should be before start_date!
start_date must not be after end_date!
end_date must not be before start_date!
I tried it with custom predicates, the only problem being that I want the predicates
only to be evaluated if the dates are filled otherwise not.
Any suggestions? Not sure if dry validation blocks are the best match for this