Class: Dry::Validation::Contract

Inherits:
Object
  • Object
show all
Extended by:
Initializer, ClassInterface
Defined in:
lib/dry/validation/contract.rb,
lib/dry/validation/contract/class_interface.rb,
lib/dry/validation/extensions/predicates_as_macros.rb

Overview

Extension to use dry-logic predicates as macros.

Examples:

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'

See Also:

Defined Under Namespace

Modules: ClassInterface

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ClassInterface

__schema__, build, inherited, json, params, rule

Methods included from Macros::Registrar

#register_macro

Instance Attribute Details

#configConfig (readonly)

Returns Contract's configuration object.


63
# File 'lib/dry/validation/contract.rb', line 63

option :config, default: -> { self.class.config }

#macrosMacros::Container (readonly)

Returns Configured macros.


69
# File 'lib/dry/validation/contract.rb', line 69

option :macros, default: -> { config.macros }

#message_resolverMessages::Resolver (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


84
# File 'lib/dry/validation/contract.rb', line 84

option :message_resolver, default: -> { Messages::Resolver.new(messages) }

#rulesHash (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


79
# File 'lib/dry/validation/contract.rb', line 79

option :rules, default: -> { self.class.rules }

#schemaDry::Schema::Params, ... (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


74
# File 'lib/dry/validation/contract.rb', line 74

option :schema, default: -> { self.class.__schema__ || raise(SchemaMissingError, self.class) }

Class Method Details

.import_predicates_as_macrosObject

Make macros available for self and its descendants.


61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/dry/validation/extensions/predicates_as_macros.rb', line 61

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

Instance Method Details

#call(input) ⇒ Result

Apply the contract to an input


93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/dry/validation/contract.rb', line 93

def call(input)
  Result.new(schema.(input), Concurrent::Map.new) do |result|
    rules.each do |rule|
      next if rule.keys.any? { |key| error?(result, key) }

      rule_result = rule.(self, result)

      rule_result.failures.each do |failure|
        result.add_error(message_resolver.(**failure))
      end
    end
  end
end

#inspectString

Return a nice string representation


112
113
114
# File 'lib/dry/validation/contract.rb', line 112

def inspect
  %(#<#{self.class} schema=#{schema.inspect} rules=#{rules.inspect}>)
end