I find the current method of reusing custom predicates across schemas (as shown in the docs) not easy enough, mainly because of the need to configure the error messages for my custom predicates in each schema that uses them.
I would want to be able to define my custom predicates along with their corresponding error messages, and easily include them (the predicates+their error messages) in my schemas.
The solution I’ve managed to come up with is to define a configuration proc
in the module that contains my custom predicates, and run it in the context of the schema:
module ValidationPredicates
CONFIGURATION = proc do
configure do
predicates(CustomPredicates)
def self.messages
super.merge(en: { errors: { email?: 'must be a valid email address' } })
end
end
end
module CustomPredicates
include Dry::Logic::Predicates
predicate(:email?) do |value|
! /magical-regex-that-matches-emails/.match(value).nil?
end
end
end
schema = Dry::Validation.Schema do
instance_eval &ValidationPredicates::CONFIGURATION
required(:email).filled(:str?, :email?)
end
This way I can define my custom predicates along with their messages in the same place, and include them in my schemas with a single line of code. But the instance_eval
here, and the proc
being executed in the schema’s context just looks a bit weird.
Is there a better way to achieve this level of reusability?