Class: Axn::Validation::Subfields

Inherits:
Object
  • Object
show all
Includes:
ActiveModel::Validations
Defined in:
lib/axn/core/validation/subfields.rb

Constant Summary collapse

ModelValidator =

NOTE: defining classes where needed b/c we explicitly register it’ll affect ALL the consuming apps’ validators as well

Validators::ModelValidator
TypeValidator =
Validators::TypeValidator
ValidateValidator =
Validators::ValidateValidator
OfValidator =
Validators::OfValidator
ShapeValidator =
Validators::ShapeValidator

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(source) ⇒ Subfields

Returns a new instance of Subfields.



17
18
19
# File 'lib/axn/core/validation/subfields.rb', line 17

def initialize(source)
  @source = source
end

Class Method Details

.collect_errors(field:, validations:, source:, action: nil) ⇒ Object

Non-raising variant: returns the ActiveModel::Errors (empty if valid).



37
38
39
# File 'lib/axn/core/validation/subfields.rb', line 37

def self.collect_errors(field:, validations:, source:, action: nil)
  errors_for(validator_class_for(field:, validations:), source:, validations:, action:)
end

.errors_for(validator_class, source:, validations:, action: nil) ⇒ Object

Runs a validator class against a source and returns its ActiveModel::Errors (empty if valid).



53
54
55
56
57
58
59
60
61
62
# File 'lib/axn/core/validation/subfields.rb', line 53

def self.errors_for(validator_class, source:, validations:, action: nil)
  validator = validator_class.new(source)

  # Set the action context for model field resolution
  validator.instance_variable_set(:@action, action)
  validator.instance_variable_set(:@validations, validations)

  validator.valid?
  validator.errors
end

.validate!(field:, validations:, source:, exception_klass:, action: nil) ⇒ Object

Raises:

  • (exception_klass)


31
32
33
34
# File 'lib/axn/core/validation/subfields.rb', line 31

def self.validate!(field:, validations:, source:, exception_klass:, action: nil)
  errors = collect_errors(field:, validations:, source:, action:)
  raise exception_klass, errors if errors.any?
end

.validator_class_for(field:, validations:) ⇒ Object

Builds the one-off validator class for a (field, validations) pair. Callers that validate the same contract repeatedly (e.g. ShapeValidator over array elements) can build this once and reuse it across sources via .errors_for, avoiding per-call class compilation.



44
45
46
47
48
49
50
# File 'lib/axn/core/validation/subfields.rb', line 44

def self.validator_class_for(field:, validations:)
  Class.new(self) do
    def self.name = "Axn::Validation::Subfields::OneOff"

    validates field, **validations
  end
end

Instance Method Details

#read_attribute_for_validation(attr) ⇒ Object



21
22
23
24
25
26
27
28
29
# File 'lib/axn/core/validation/subfields.rb', line 21

def read_attribute_for_validation(attr)
  # Only use action's reader methods for model fields that need special resolution
  # For all other fields, use the unified FieldResolvers system
  if @action && @validations&.key?(:model) && @action.respond_to?(attr)
    @action.public_send(attr)
  else
    Axn::Core::FieldResolvers.resolve(type: :extract, field: attr, provided_data: @source)
  end
end