Class: Dry::Validation::Rust::Schema

Inherits:
Object
  • Object
show all
Defined in:
lib/dry/validation/rust/schema.rb,
lib/dry/validation/rust/schema.rb,
lib/dry/validation/rust/schema/dsl.rb,
lib/dry/validation/rust/schema/result.rb,
lib/dry/validation/rust/generated_predicates.rb,
lib/dry/validation/rust/schema/field_builder.rb,
lib/dry/validation/rust/schema/predicate_block.rb,
lib/dry/validation/rust/schema/processor_hooks.rb,
lib/dry/validation/rust/schema/field_definition.rb,
lib/dry/validation/rust/schema/ruby_type_processor.rb

Overview

A compiled schema that validates and coerces input hashes.

Examples:

Define and call a schema

schema = Dry::Validation::Rust::Schema.Params do
  required(:age).value(:integer)
end
result = schema.call("age" => "25")
result.to_h # => { age: 25 }

Defined Under Namespace

Classes: DSL, FieldBuilder, FieldDefinition, Predicate, PredicateBlock, ProcessorHooks, Result, RubyTypeProcessor

Constant Summary collapse

TYPES =

Type symbols supported by schema fields.

Returns:

  • (Array<Symbol>)
%i[
  any nil bool true false integer float decimal string symbol array hash
  date date_time datetime time
].freeze
NATIVE_PREDICATES =
%i[gt gteq lt lteq min_size max_size size odd even].freeze
RUBY_PREDICATES =
%i[format included_in excluded_from eql not_eql].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(mode:, fields:, before_hooks: [], after_hooks: [], validate_keys: false, messages: MessageConfig.new) ⇒ Schema

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.

Compiles field definitions into a native schema plan.

Parameters:

  • mode (Symbol)

    the input mode.

  • fields (Array<FieldDefinition>)

    field definitions to compile.

  • before_hooks (Array<#call>) (defaults to: [])

    processors run before native validation.

  • after_hooks (Array<#call>) (defaults to: [])

    processors run after native validation.

  • validate_keys (Boolean) (defaults to: false)

    whether unknown keys are validation errors.

  • messages (MessageConfig) (defaults to: MessageConfig.new)

    validation message configuration.

Raises:



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

def initialize(mode:, fields:, before_hooks: [], after_hooks: [], validate_keys: false,
               messages: MessageConfig.new)
  @mode = mode.to_sym
  @fields = fields.freeze
  @fields_by_name = fields.to_h { |field| [field.name, field] }.freeze
  @has_ruby_predicates = ruby_predicates?(fields)
  @before_hooks, @after_hooks = [before_hooks, after_hooks].map { _1.dup.freeze }
  @message_backend = messages.backend_class.new(messages)
  begin
    plan = {
      engine_version: ENGINE_VERSION,
      mode: mode.to_s,
      validate_keys: validate_keys,
      fields: fields.map(&:to_native_h)
    }
    @engine = Native::Engine.new(JSON.generate(plan, max_nesting: false))
  rescue StandardError => e
    raise NativeExtensionError, "could not compile native schema plan: #{e.message}"
  end
end

Instance Attribute Details

#engineNative::Engine (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 the native engine that executes this schema.

Returns:

  • (Native::Engine)

    the native engine that executes this schema.



54
55
56
# File 'lib/dry/validation/rust/schema.rb', line 54

def engine
  @engine
end

#fieldsArray<FieldDefinition> (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 the compiled top-level field definitions.

Returns:



50
51
52
# File 'lib/dry/validation/rust/schema.rb', line 50

def fields
  @fields
end

#modeSymbol (readonly)

Returns the schema input mode.

Returns:

  • (Symbol)

    the schema input mode.



46
47
48
# File 'lib/dry/validation/rust/schema.rb', line 46

def mode
  @mode
end

Class Method Details

.define(mode = :schema, *external_schemas) { ... } ⇒ Schema

Builds a schema from a DSL block and optional schemas to import.

Parameters:

  • mode (Symbol) (defaults to: :schema)

    the input mode, such as :schema, :params, or :json.

  • external_schemas (Array<Schema>)

    compiled schemas whose fields are imported.

Yields:

  • the schema DSL block.

Returns:

  • (Schema)

    the compiled schema.



62
63
64
65
66
67
# File 'lib/dry/validation/rust/schema.rb', line 62

def self.define(mode = :schema, *external_schemas, &block)
  dsl = DSL.new(mode: mode)
  external_schemas.each { |schema| dsl.import(schema) }
  dsl.instance_eval(&block) if block
  dsl.compile
end

.JSON(*external_schemas) { ... } ⇒ Schema

Builds a schema that coerces JSON-compatible input.

Parameters:

  • external_schemas (Array<Schema>)

    compiled schemas whose fields are imported.

Yields:

  • the schema DSL block.

Returns:

  • (Schema)

    the compiled JSON-mode schema.



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

def self.JSON(*external_schemas, &) = define(:json, *external_schemas, &)

.Params(*external_schemas) { ... } ⇒ Schema

Builds a schema that coerces web request parameter input.

Parameters:

  • external_schemas (Array<Schema>)

    compiled schemas whose fields are imported.

Yields:

  • the schema DSL block.

Returns:

  • (Schema)

    the compiled params-mode schema.



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

def self.Params(*external_schemas, &) = define(:params, *external_schemas, &)

Instance Method Details

#[](input) ⇒ Result

Validates and coerces a Hash.

Alias for #call.

Parameters:

  • input (Hash)

    input to validate.

Returns:

  • (Result)

    the output and validation messages.

Raises:

  • (ArgumentError)

    if input is not a Hash.



147
148
149
# File 'lib/dry/validation/rust/schema.rb', line 147

def [](input)
  call(input)
end

#call(input) ⇒ Result

Validates and coerces a Hash.

Parameters:

  • input (Hash)

    input to validate.

Returns:

  • (Result)

    the output and validation messages.

Raises:

  • (ArgumentError)

    if input is not a Hash.



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/dry/validation/rust/schema.rb', line 120

def call(input)
  raise ArgumentError, "Input must be a Hash. #{input.class} was given." unless input.is_a?(Hash)

  # Before hooks receive an isolated copy and may safely mutate nested values.
  prepared_input = before_hooks.empty? ? input.dup : ProcessorHooks.deep_dup(input)
  prepared_input = ProcessorHooks.apply(before_hooks, prepared_input)
  result = engine.call(prepared_input)
  output = ProcessorHooks.apply(after_hooks, result.output)
  messages = result.errors.map do |error|
    path = error[:path]
    code = error[:code]
    text = error[:text]
    predicate, args = native_predicate_details(path, code)
    native_message(path, code, text, predicate, args)
  end
  RubyTypeProcessor.apply(fields, output, messages, @message_backend)
  apply_ruby_predicates(fields, output, [], messages) if @has_ruby_predicates
  Result.new(output, messages.freeze)
end

#inspectString

Returns a diagnostic representation of this compiled schema.

Returns:

  • (String)

    the schema mode, field names, and native-engine marker.



164
165
166
# File 'lib/dry/validation/rust/schema.rb', line 164

def inspect
  "#<#{self.class} mode=#{mode.inspect} fields=#{fields.map(&:name).inspect} native=true>"
end

#key_pathsArray<Array<Symbol, Integer>>

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 all declared field paths, including nested array paths.

Returns:

  • (Array<Array<Symbol, Integer>>)

    declared field paths. Array members use :__index__ as an index placeholder.



157
158
159
# File 'lib/dry/validation/rust/schema.rb', line 157

def key_paths
  paths_for(fields)
end