Reusing custom validation predicates


#1

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?