73 lines
2.0 KiB
Ruby
73 lines
2.0 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Dry
|
|
module Validation
|
|
# Predicate registry with additional needed methods.
|
|
class PredicateRegistry < Schema::PredicateRegistry
|
|
# List of predicates to be imported by `:predicates_as_macros`
|
|
# extension.
|
|
#
|
|
# @see Dry::Validation::Contract
|
|
WHITELIST = %i[
|
|
filled? format? gt? gteq? included_in? includes? inclusion? is? lt?
|
|
lteq? max_size? min_size? not_eql? odd? respond_to? size? true?
|
|
uuid_v4?
|
|
].freeze
|
|
|
|
# @api private
|
|
def arg_names(name)
|
|
arg_list(name).map(&:first)
|
|
end
|
|
|
|
# @api private
|
|
def call(name, args)
|
|
self[name].(*args)
|
|
end
|
|
|
|
# @api private
|
|
def message_opts(name, arg_values)
|
|
arg_names(name).zip(arg_values).to_h
|
|
end
|
|
end
|
|
|
|
# Extension to use dry-logic predicates as macros.
|
|
#
|
|
# @see Dry::Validation::PredicateRegistry::WHITELIST Available predicates
|
|
#
|
|
# @example
|
|
# Dry::Validation.load_extensions(:predicates_as_macros)
|
|
#
|
|
# class ApplicationContract < Dry::Validation::Contract
|
|
# import_predicates_as_macros
|
|
# end
|
|
#
|
|
# class AgeContract < ApplicationContract
|
|
# schema do
|
|
# required(:age).filled(:integer)
|
|
# end
|
|
#
|
|
# rule(:age).validate(gteq?: 18)
|
|
# end
|
|
#
|
|
# AgeContract.new.(age: 17).errors.first.text
|
|
# # => 'must be greater than or equal to 18'
|
|
#
|
|
# @api public
|
|
class Contract
|
|
# Make macros available for self and its descendants.
|
|
def self.import_predicates_as_macros
|
|
registry = PredicateRegistry.new
|
|
|
|
PredicateRegistry::WHITELIST.each do |name|
|
|
register_macro(name) do |macro:|
|
|
predicate_args = [*macro.args, value]
|
|
message_opts = registry.message_opts(name, predicate_args)
|
|
|
|
key.failure(name, message_opts) unless registry.(name, predicate_args)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|