Sha256: 25e2316791f4b66c5e94351482fc97fb835872a6cc7348726efe6bb1efb4fb02

Contents?: true

Size: 1.37 KB

Versions: 1

Compression:

Stored size: 1.37 KB

Contents

require 'set'

module Structor
  class Node
    attr_reader :required

    def initialize(type, required, &block)
      @type = Type.new(type)
      @required = required
      @children = block_given? ? Builder.new(&block).nodes : []
      @errors = []
    end

    def check(structure)
      clear_errors

      if @type.check(structure)
        if @children.any? && structure.is_a?(Hash)
          key_set = structure.keys.to_set

          unless required_keys <= key_set
            @errors << "missing keys: #{(required_keys - key_set).to_a}"
          end

          unless key_set <= permitted_keys
            @errors << "excess keys: #{(key_set - permitted_keys).to_a}"
          end

          structure.each { |k, v| @children[k] && @children[k].check(v) }
        end
      else
        @errors << "invalid type: expected #{@type.describe}, "\
          "got #{structure.class.name}"
      end

      errors.empty?
    end

    def errors
      @errors + @children.map do |key, node|
        node.errors.map { |e| "#{key.inspect} => #{e}" }
      end.flatten
    end

    def clear_errors
      @errors.clear
      @children.each { |k, v| v.clear_errors }
    end

    private

    def permitted_keys
      @permitted_keys ||= @children.keys.to_set
    end

    def required_keys
      @required_keys ||=
        @children.select { |k, v| v.required }.map(&:first).to_set
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
structor-0.0.1 lib/structor/node.rb