class NxtSchema::Template::Base
Attributes
additional_keys_strategy[RW]
configuration[R]
context[RW]
key_transformer[R]
maybe_evaluators[RW]
meta[RW]
name[RW]
on_evaluators[RW]
options[RW]
parent_node[RW]
path[RW]
root_node[RW]
type[RW]
type_system[R]
validations[R]
Public Class Methods
new(name:, type:, parent_node:, **options, &block)
click to toggle source
# File lib/nxt_schema/template/base.rb, line 4 def initialize(name:, type:, parent_node:, **options, &block) resolve_name(name) @parent_node = parent_node @options = options @is_root_node = parent_node.nil? @root_node = parent_node.nil? ? self : parent_node.root_node @path = resolve_path @on_evaluators = [] @maybe_evaluators = [] @validations = [] @configuration = block resolve_key_transformer resolve_context resolve_optional_option resolve_omnipresent_option resolve_type_system resolve_type(type) resolve_additional_keys_strategy node_class # memoize configure(&block) if block_given? end
Public Instance Methods
apply(input: Undefined.new, context: self.context, parent: nil, error_key: nil)
click to toggle source
# File lib/nxt_schema/template/base.rb, line 45 def apply(input: Undefined.new, context: self.context, parent: nil, error_key: nil) build_node(input: input, context: context, parent: parent, error_key: error_key).call end
apply!(input: Undefined.new, context: self.context, parent: nil, error_key: nil)
click to toggle source
# File lib/nxt_schema/template/base.rb, line 49 def apply!(input: Undefined.new, context: self.context, parent: nil, error_key: nil) result = build_node(input: input, context: context, parent: parent, error_key: error_key).call return result if parent raise NxtSchema::Errors::Invalid.new(result) if result.errors.any? result.output end
build_node(input: Undefined.new, context: self.context, parent: nil, error_key: nil)
click to toggle source
# File lib/nxt_schema/template/base.rb, line 58 def build_node(input: Undefined.new, context: self.context, parent: nil, error_key: nil) node_class.new( node: self, input: input, parent: parent, context: context, error_key: error_key ) end
default(value = NxtSchema::Undefined.new, &block)
click to toggle source
# File lib/nxt_schema/template/base.rb, line 80 def default(value = NxtSchema::Undefined.new, &block) value = missing_input?(value) ? block : value condition = ->(input) { missing_input?(input) || input.nil? } on(condition, value) self end
maybe(value = NxtSchema::Undefined.new, &block)
click to toggle source
# File lib/nxt_schema/template/base.rb, line 95 def maybe(value = NxtSchema::Undefined.new, &block) value = missing_input?(value) ? block : value maybe_evaluators << MaybeEvaluator.new(value: value) self end
omnipresent?()
click to toggle source
# File lib/nxt_schema/template/base.rb, line 76 def omnipresent? @omnipresent end
on(condition, value = NxtSchema::Undefined.new, &block)
click to toggle source
# File lib/nxt_schema/template/base.rb, line 88 def on(condition, value = NxtSchema::Undefined.new, &block) value = missing_input?(value) ? block : value on_evaluators << OnEvaluator.new(condition: condition, value: value) self end
optional?()
click to toggle source
# File lib/nxt_schema/template/base.rb, line 72 def optional? @optional end
root_node?()
click to toggle source
# File lib/nxt_schema/template/base.rb, line 68 def root_node? @is_root_node end
validate(key = NxtSchema::Undefined.new, *args, &block)
click to toggle source
# File lib/nxt_schema/template/base.rb, line 102 def validate(key = NxtSchema::Undefined.new, *args, &block) # TODO: This does not really work with all kinds of chaining combinations yet! validator = if key.is_a?(Symbol) validator(key, *args) elsif key.respond_to?(:call) key elsif block_given? if key.is_a?(NxtSchema::Undefined) block else configure(&block) end else raise ArgumentError, "Don't know how to resolve validator from: #{key} with: #{args} #{block}" end register_validator(validator) self end
validate_with(&block)
click to toggle source
# File lib/nxt_schema/template/base.rb, line 124 def validate_with(&block) proxy = ->(node) { NxtSchema::Validator::ValidateWithProxy.new(node).validate(&block) } register_validator(proxy) end
Private Instance Methods
configure(&block)
click to toggle source
# File lib/nxt_schema/template/base.rb, line 159 def configure(&block) if block.arity == 1 block.call(self) else instance_exec(&block) end end
missing_input?(value)
click to toggle source
# File lib/nxt_schema/template/base.rb, line 205 def missing_input?(value) value.is_a? Undefined end
node_class()
click to toggle source
# File lib/nxt_schema/template/base.rb, line 155 def node_class @node_class ||= "NxtSchema::Node::#{self.class.name.demodulize}".constantize end
register_validator(validator)
click to toggle source
# File lib/nxt_schema/template/base.rb, line 137 def register_validator(validator) validations << validator end
resolve_additional_keys_strategy()
click to toggle source
# File lib/nxt_schema/template/base.rb, line 167 def resolve_additional_keys_strategy @additional_keys_strategy = options.fetch(:additional_keys) do parent_node&.send(:additional_keys_strategy) || :allow end end
resolve_context()
click to toggle source
# File lib/nxt_schema/template/base.rb, line 201 def resolve_context self.context = options.fetch(:context) { parent_node&.send(:context) } end
resolve_key_transformer()
click to toggle source
# File lib/nxt_schema/template/base.rb, line 209 def resolve_key_transformer @key_transformer = options.fetch(:transform_keys) { parent_node&.key_transformer || ->(key) { key.to_sym } } end
resolve_name(name)
click to toggle source
# File lib/nxt_schema/template/base.rb, line 213 def resolve_name(name) raise ArgumentError, 'Name can either be a symbol or an integer' unless name.class.in?([Symbol, Integer]) @name = name end
resolve_omnipresent_option()
click to toggle source
# File lib/nxt_schema/template/base.rb, line 189 def resolve_omnipresent_option omnipresent = options.fetch(:omnipresent, false) raise Errors::InvalidOptions, 'Omnipresent nodes are only available within schemas' if omnipresent && !parent_node.is_a?(Schema) raise Errors::InvalidOptions, "Can't make omnipresent node optional" if optional? && omnipresent @omnipresent = omnipresent end
resolve_optional_option()
click to toggle source
# File lib/nxt_schema/template/base.rb, line 173 def resolve_optional_option optional = options.fetch(:optional, false) raise Errors::InvalidOptions, 'Optional nodes are only available within schemas' if optional && !parent_node.is_a?(Schema) raise Errors::InvalidOptions, "Can't make omnipresent node optional" if optional && omnipresent? if optional.respond_to?(:call) # When a node is conditionally optional we make it optional and add a validator to the parent to check # that it's there when the option does not apply. optional_node_validator = validator(:optional_node, optional, name) parent_node.send(:register_validator, optional_node_validator) @optional = true else @optional = optional end end
resolve_path()
click to toggle source
# File lib/nxt_schema/template/base.rb, line 197 def resolve_path self.path = root_node? ? name : "#{parent_node.path}.#{name}" end
resolve_type(name_or_type)
click to toggle source
# File lib/nxt_schema/template/base.rb, line 141 def resolve_type(name_or_type) @type = root_node.send(:type_resolver).resolve(type_system, name_or_type) end
resolve_type_system()
click to toggle source
# File lib/nxt_schema/template/base.rb, line 145 def resolve_type_system @type_system = TypeSystemResolver.new(node: self).call end
type_resolver()
click to toggle source
# File lib/nxt_schema/template/base.rb, line 149 def type_resolver @type_resolver ||= begin root_node? ? TypeResolver.new : (raise NoMethodError, 'type_resolver is only available on root node') end end
validator(key, *args)
click to toggle source
# File lib/nxt_schema/template/base.rb, line 133 def validator(key, *args) Validators::REGISTRY.resolve!(key).new(*args).build end