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

Instance Attribute Details

#configConfig (readonly)

Returns Contract's configuration object.

Returns:

  • (Config)

    Contract's configuration object



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

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

#default_contextHash (readonly)

Returns Default context for rules.

Returns:

  • (Hash)

    Default context for rules



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

option :default_context, default: -> { EMPTY_HASH }

#macrosMacros::Container (readonly)

Returns Configured macros.

Returns:

See Also:



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

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.

Returns:



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

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.

Returns:

  • (Hash)


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

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.

Returns:

  • (Dry::Schema::Params, Dry::Schema::JSON, Dry::Schema::Processor)


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

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

Class Method Details

.__schema__Object Originally defined in module ClassInterface

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.

.build(options = EMPTY_HASH, &block) ⇒ Contract Originally defined in module ClassInterface

A shortcut that can be used to define contracts that won't be reused or inherited

Examples:

my_contract = Dry::Validation::Contract.build do
  params do
    required(:name).filled(:string)
  end
end

my_contract.call(name: "Jane")

Returns:

.configConfig Originally defined in module ClassInterface

Configuration

Examples:

class MyContract < Dry::Validation::Contract
  config.messages.backend = :i18n
end

Returns:

.import_predicates_as_macrosObject

Make macros available for self and its descendants.



58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/dry/validation/extensions/predicates_as_macros.rb', line 58

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

.inherited(klass) ⇒ Object Originally defined in module ClassInterface

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.

.json(*external_schemas, &block) ⇒ Dry::Schema::JSON, NilClass Originally defined in module ClassInterface

Define a JSON schema for your contract

This type of schema is suitable for JSON data

Returns:

  • (Dry::Schema::JSON, NilClass)

See Also:

.macrosMacros::Container Originally defined in module ClassInterface

Return macros registered for this class

Returns:

.messagesDry::Schema::Messages Originally defined in module ClassInterface

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.

Return messages configured for this class

Returns:

  • (Dry::Schema::Messages)

.params(*external_schemas, &block) ⇒ Dry::Schema::Params, NilClass Originally defined in module ClassInterface

Define a params schema for your contract

This type of schema is suitable for HTTP parameters

Returns:

  • (Dry::Schema::Params, NilClass)

See Also:

.register_macro(name, *args, &block) ⇒ self Originally defined in module Macros::Registrar

Register a macro

Examples:

register a global macro

Dry::Validation.register_macro(:even_numbers) do
  key.failure('all numbers must be even') unless values[key_name].all?(&:even?)
end

register a contract macro

class MyContract < Dry::Validation::Contract
  register_macro(:even_numbers) do
    key.failure('all numbers must be even') unless values[key_name].all?(&:even?)
  end
end

Parameters:

  • name (Symbol)

    The name of the macro

  • args (Array)

    Optional default positional arguments for the macro

Returns:

  • (self)

See Also:

.rule(*keys, &block) ⇒ Rule Originally defined in module ClassInterface

Define a rule for your contract

Examples:

using a symbol

rule(:age) do
  failure('must be at least 18') if values[:age] < 18
end

using a path to a value and a custom predicate

rule('address.street') do
  failure('please provide a valid street address') if valid_street?(values[:street])
end

Returns:

.rulesArray<Rule> Originally defined in module ClassInterface

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.

Return rules defined in this class

Returns:

.schema(*external_schemas, &block) ⇒ Dry::Schema::Processor, NilClass Originally defined in module ClassInterface

Define a plain schema for your contract

This type of schema does not offer coercion out of the box

Returns:

  • (Dry::Schema::Processor, NilClass)

See Also:

Instance Method Details

#call(input, context = EMPTY_HASH) ⇒ Result

Apply the contract to an input

rubocop: disable Metrics/AbcSize

Parameters:

  • input (Hash)

    The input to validate

  • context (Hash) (defaults to: EMPTY_HASH)

    Initial context for rules

Returns:



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/dry/validation/contract.rb', line 92

def call(input, context = EMPTY_HASH)
  validate_input_type(input)

  context_map = Concurrent::Map.new.tap do |map|
    default_context.each { |key, value| map[key] = value }
    context.each { |key, value| map[key] = value }
  end

  Result.new(schema.(input), context_map) 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

Returns:

  • (String)


119
120
121
# File 'lib/dry/validation/contract.rb', line 119

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