class Schemacop::V2::NodeSupportingType

Public Class Methods

build(options, &block) click to toggle source
# File lib/schemacop/v2/node_supporting_type.rb, line 5
def self.build(options, &block)
  new(nil, options, &block)
end
new(options = {}, &block) click to toggle source
Calls superclass method
# File lib/schemacop/v2/node_supporting_type.rb, line 9
def initialize(options = {}, &block)
  super(options)

  @types = []
  exec_block(&block)

  if @types.none?
    fail Exceptions::InvalidSchemaError, 'Block must contain a type definition or not be given at all.' if block_given?

    type :object
  end

  # if @types.none?
  #   super(options)
  #   exec_block(&block)
  #   if @types.none?
  #     fail Exceptions::InvalidSchemaError, 'Block must contain a type definition or not be given at all.' if block_given?
  #   end
  # else
  #   super({})
  # end
end

Public Instance Methods

exec_block(&block) click to toggle source
Calls superclass method
# File lib/schemacop/v2/node_supporting_type.rb, line 32
def exec_block(&block)
  super
rescue NoMethodError
  @types = []
  type :hash, &block
end
type(*args, **kwargs, &block) click to toggle source

required signature: First argument must be a type or an array of types Following arguments may be subtypes Last argument may be an options hash. Options and given block are passed to the last specified type. Not permitted to give subtypes / options / a block if an array of types is given.

TODO: Probably change this method so that the 'rescue NoMethodError' happens in here directly and not in the constructor. This way we can always call 'type', even if we don't have one and the type is auto-guessed as it formerly was the case in the constructor.

# File lib/schemacop/v2/node_supporting_type.rb, line 50
def type(*args, **kwargs, &block)
  options = kwargs
  types = [*args.shift]
  subtypes = args

  unless types.any?
    fail Exceptions::InvalidSchemaError, 'At least one type must be given.'
  end

  if subtypes.any? && types.size > 1
    fail Exceptions::InvalidSchemaError, "First given type can't be an array if subtypes are given."
  end

  if types.size > 1 && options.any?
    fail Exceptions::InvalidSchemaError, 'No options can be specified if multiple types are given.'
  end

  types.each do |type|
    klass = resolve_type_klass(type)

    if subtypes.any?
      unless klass <= NodeSupportingType
        fail "Node #{klass} does not support subtypes."
      end

      child = klass.new do
        self.type(*subtypes, **options, &block)
      end

      # child = klass.build(options)
      #
      #
      # child.type(*subtypes, &block)
    else
      if klass == ObjectValidator && type.is_a?(Class)
        options[:classes] = type
      end

      child = klass.new(options, &block)
    end

    @types << child
  end
end
validate(data, collector) click to toggle source
Calls superclass method
# File lib/schemacop/v2/node_supporting_type.rb, line 95
def validate(data, collector)
  super
  validate_types(data, collector)
end

Protected Instance Methods

cast!(data, collector) click to toggle source
# File lib/schemacop/v2/node_supporting_type.rb, line 102
def cast!(data, collector)
  @types.each do |type|
    next unless type.option?(:cast) && !type.type_matches?(data) && type.type_filter_matches?(data)

    caster = Caster.new(type.option(:cast), data, type.class.klasses.first)

    next unless caster.castable?

    begin
      data = caster.cast
      collector.override_value(data)
      return data
    rescue Exceptions::InvalidSchemaError => e
      collector.error e.message
    end
  end

  return data
end
validate_types(data, collector) click to toggle source
# File lib/schemacop/v2/node_supporting_type.rb, line 122
def validate_types(data, collector)
  data = cast!(data, collector)
  unless (match = @types.find { |t| t.type_matches?(data) })
    allowed_types = @types.map(&:type_label)

    collector.error "Data type not matching: #{data.class}, allowed types: #{allowed_types.join('; ')}"
    return
  end
  match.validate(data, collector)
end