class Schemacop::V3::Node

Attributes

as[R]
default[R]
description[R]
name[R]
options[R]
parent[R]
title[R]

Public Class Methods

allowed_options() click to toggle source
# File lib/schemacop/v3/node.rb, line 51
def self.allowed_options
  %i[name required default description examples enum parent options title as]
end
create(type = self, **options, &block) click to toggle source
# File lib/schemacop/v3/node.rb, line 27
def self.create(type = self, **options, &block)
  klass = resolve_class(type)
  fail "Could not find node for type #{type.inspect}." unless klass

  node = klass.new(**options, &block)

  if options.delete(:cast_str)
    format = NodeRegistry.name(klass)
    one_of_options = {
      required:           options.delete(:required),
      treat_blank_as_nil: true,
      name:               options.delete(:name),
      as:                 options.delete(:as),
      description:        options.delete(:description)
    }
    node = create(:one_of, **one_of_options) do
      self.node node
      str format: format, format_options: options
    end
  end

  return node
end
dsl_methods() click to toggle source
# File lib/schemacop/v3/node.rb, line 55
def self.dsl_methods
  %i[dsl_scm dsl_node]
end
new(**options, &block) click to toggle source
# File lib/schemacop/v3/node.rb, line 71
def initialize(**options, &block)
  # Check options #
  disallowed_options = options.keys - self.class.allowed_options

  if disallowed_options.any?
    fail Schemacop::Exceptions::InvalidSchemaError, "Options #{disallowed_options.inspect} are not allowed for this node."
  end

  # Assign attributes #
  @name = options.delete(:name)
  @name = @name.to_s unless @name.nil? || @name.is_a?(Regexp)
  @as = options.delete(:as)
  @required = !!options.delete(:required)
  @default = options.delete(:default)
  @title = options.delete(:title)
  @description = options.delete(:description)
  @examples = options.delete(:examples)
  @enum = options.delete(:enum)&.to_set
  @parent = options.delete(:parent)
  @options = options
  @schemas = {}

  # Run subclass init #
  init

  # Run DSL block #
  if block_given?
    unless self.class.supports_children_options
      fail Schemacop::Exceptions::InvalidSchemaError, "Node #{self.class} does not support blocks."
    end

    scope = DslScope.new(self)
    env = ScopedEnv.new(self, self.class.dsl_methods, scope, :dsl_)
    env.instance_exec(&block)
  end

  # Validate self #
  begin
    validate_self
  rescue StandardError => e
    fail Exceptions::InvalidSchemaError, e.message
  end
end
resolve_class(type) click to toggle source
# File lib/schemacop/v3/node.rb, line 23
def self.resolve_class(type)
  NodeRegistry.find(type)
end
supports_children(name: false) click to toggle source
# File lib/schemacop/v3/node.rb, line 15
def self.supports_children(name: false)
  self._supports_children = { name: name }
end
supports_children_options() click to toggle source
# File lib/schemacop/v3/node.rb, line 19
def self.supports_children_options
  _supports_children
end

Public Instance Methods

allowed_types() click to toggle source
# File lib/schemacop/v3/node.rb, line 59
def allowed_types
  {}
end
as_json() click to toggle source
# File lib/schemacop/v3/node.rb, line 138
def as_json
  process_json([], {})
end
cast(value) click to toggle source
# File lib/schemacop/v3/node.rb, line 142
def cast(value)
  value || default
end
children() click to toggle source
# File lib/schemacop/v3/node.rb, line 67
def children
  []
end
create(type, **options, &block) click to toggle source
# File lib/schemacop/v3/node.rb, line 115
def create(type, **options, &block)
  options[:parent] = self
  return Node.create(type, **options, &block)
end
dsl_node(node, *_args, **_kwargs) click to toggle source
# File lib/schemacop/v3/node.rb, line 126
def dsl_node(node, *_args, **_kwargs)
  add_child node
end
dsl_scm(name, type = :hash, **options, &block) click to toggle source
# File lib/schemacop/v3/node.rb, line 122
def dsl_scm(name, type = :hash, **options, &block)
  @schemas[name] = create(type, **options, &block)
end
init() click to toggle source
# File lib/schemacop/v3/node.rb, line 120
def init; end
required?() click to toggle source
# File lib/schemacop/v3/node.rb, line 134
def required?
  @required
end
schemas() click to toggle source
# File lib/schemacop/v3/node.rb, line 130
def schemas
  (parent&.schemas || {}).merge(@schemas)
end
used_external_schemas() click to toggle source
# File lib/schemacop/v3/node.rb, line 63
def used_external_schemas
  children.map(&:used_external_schemas).flatten.uniq
end
validate(data) click to toggle source
# File lib/schemacop/v3/node.rb, line 146
def validate(data)
  result = Result.new(self, data)
  _validate(data, result: result)
  return result
end

Protected Instance Methods

_validate(data, result:) click to toggle source
# File lib/schemacop/v3/node.rb, line 191
def _validate(data, result:)
  # Validate nil #
  if data.nil? && required?
    result.error 'Value must be given.'
    return nil
  end

  # Apply default #
  if data.nil?
    if default
      data = default
    else
      return nil
    end
  end

  # Validate type #
  if allowed_types.any? && allowed_types.keys.none? { |c| data.send(type_assertion_method, c) }
    collection = allowed_types.values.map { |t| "\"#{t}\"" }.uniq.sort.join(' or ')
    result.error "Invalid type, got type \"#{data.class}\", expected #{collection}."
    return nil
  end

  # Validate enums #
  if @enum && !@enum.include?(data)
    result.error "Value not included in enum #{@enum.to_a.inspect}."
  end

  return data
end
context() click to toggle source
# File lib/schemacop/v3/node.rb, line 154
def context
  Schemacop.context
end
item_matches?(item, data) click to toggle source
# File lib/schemacop/v3/node.rb, line 158
def item_matches?(item, data)
  item_result = Result.new(self)
  item._validate(data, result: item_result)
  return item_result.errors.none?
end
process_json(attrs, json) click to toggle source
# File lib/schemacop/v3/node.rb, line 164
def process_json(attrs, json)
  if !context.swagger_json? && @schemas.any?
    json[:definitions] = {}
    @schemas.each do |name, subschema|
      json[:definitions][name] = subschema.as_json
    end
  end

  attrs.each do |attr|
    if options.include?(attr)
      json[attr.to_s.camelize(:lower).to_sym] = options[attr]
    end
  end

  json[:title] = @title if @title
  json[context.swagger_json? ? :example : :examples] = @examples if @examples
  json[:description] = @description if @description
  json[:default] = @default if @default
  json[:enum] = @enum.to_a if @enum

  return json.as_json
end
type_assertion_method() click to toggle source
# File lib/schemacop/v3/node.rb, line 187
def type_assertion_method
  :is_a?
end
validate_self() click to toggle source
# File lib/schemacop/v3/node.rb, line 222
def validate_self; end