Class: RubyReactor::Validation::SchemaBuilder

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby_reactor/validation/schema_builder.rb

Class Method Summary collapse

Class Method Details

.apply_inline_rules(dsl, rules) ⇒ Object

Apply a list of inline rules ([name, type, optional, predicates]) onto a dry-schema DSL context.



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/ruby_reactor/validation/schema_builder.rb', line 72

def self.apply_inline_rules(dsl, rules)
  rules.each do |name, type, optional, predicates|
    macro_method = optional ? :optional : :required
    rule_method  = optional ? :maybe : :filled
    positional   = type.is_a?(Symbol) ? [type] : []
    kwargs       = type.is_a?(Module) ? { type?: type, **predicates } : predicates

    macro = dsl.public_send(macro_method, name)
    if kwargs.empty?
      macro.public_send(rule_method, *positional)
    else
      macro.public_send(rule_method, *positional, **kwargs)
    end
  end
end

.build_args(inline_rules, validate_input) ⇒ Object

Compose per-argument inline rules with an optional ‘validate_args` input (block or pre-built schema). Block/inline rules are applied first; a pre-built schema is merged last so its rules win.



45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/ruby_reactor/validation/schema_builder.rb', line 45

def self.build_args(inline_rules, validate_input)
  block = validate_input.is_a?(Proc) ? validate_input : nil
  prebuilt = !validate_input.nil? && block.nil? ? schema_for(validate_input) : nil

  composed = build_args_base(inline_rules, block)

  if prebuilt && composed
    composed.merge(prebuilt)
  elsif prebuilt
    prebuilt
  else
    composed
  end
end

.build_args_base(inline_rules, block) ⇒ Object



60
61
62
63
64
65
66
67
68
# File 'lib/ruby_reactor/validation/schema_builder.rb', line 60

def self.build_args_base(inline_rules, block)
  return Dry::Schema.Params(&block) if inline_rules.empty? && block
  return nil if inline_rules.empty?

  Dry::Schema.Params do
    SchemaBuilder.apply_inline_rules(self, inline_rules)
    instance_exec(&block) if block
  end
end

.build_contract_from_block(&block) ⇒ Object



12
13
14
# File 'lib/ruby_reactor/validation/schema_builder.rb', line 12

def self.build_contract_from_block(&block)
  Class.new(Dry::Validation::Contract, &block).new
end

.build_from_block(&block) ⇒ Object



8
9
10
# File 'lib/ruby_reactor/validation/schema_builder.rb', line 8

def self.build_from_block(&block)
  Dry::Schema.Params(&block)
end

.build_inline(name, type, optional, predicates) ⇒ Object

Form 1 / 1b — a single named value with an optional type and predicates.

build_inline(:age, :integer, false, { gteq?: 18 })
  => required(:age).filled(:integer, gteq?: 18)
build_inline(:user, User, false, {})
  => required(:user).filled(type?: User)
build_inline(:bio, :string, true, { max_size?: 100 })
  => optional(:bio).maybe(:string, max_size?: 100)


24
25
26
27
28
29
# File 'lib/ruby_reactor/validation/schema_builder.rb', line 24

def self.build_inline(name, type, optional, predicates)
  rules = [[name, type, optional, predicates]]
  Dry::Schema.Params do
    SchemaBuilder.apply_inline_rules(self, rules)
  end
end

.build_macro(name, optional, &block) ⇒ Object

Form 2 — the block receives the macro already bound to the name and optionality (‘required(name)` / `optional(name)`). Because it is invoked as a block argument (not via instance_eval) the caller’s ‘self` and lexical scope (class constants, helper methods) stay reachable.



35
36
37
38
39
40
# File 'lib/ruby_reactor/validation/schema_builder.rb', line 35

def self.build_macro(name, optional, &block)
  macro_method = optional ? :optional : :required
  Dry::Schema.Params do
    block.call(public_send(macro_method, name))
  end
end

.schema_for(schema_or_validator) ⇒ Object

Unwrap an InputValidator into its underlying dry-schema; pass dry-schemas through unchanged.



90
91
92
93
94
95
96
# File 'lib/ruby_reactor/validation/schema_builder.rb', line 90

def self.schema_for(schema_or_validator)
  if schema_or_validator.is_a?(RubyReactor::Validation::InputValidator)
    schema_or_validator.schema
  else
    schema_or_validator
  end
end