schemacop 2.4.5 → 3.0.0.rc2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/.gitignore +3 -0
 - data/.rubocop.yml +25 -1
 - data/.travis.yml +3 -1
 - data/CHANGELOG.md +32 -1
 - data/README.md +53 -710
 - data/README_V2.md +775 -0
 - data/README_V3.md +1195 -0
 - data/Rakefile +8 -12
 - data/VERSION +1 -1
 - data/lib/schemacop.rb +35 -36
 - data/lib/schemacop/base_schema.rb +37 -0
 - data/lib/schemacop/railtie.rb +10 -0
 - data/lib/schemacop/schema.rb +1 -60
 - data/lib/schemacop/schema2.rb +22 -0
 - data/lib/schemacop/schema3.rb +21 -0
 - data/lib/schemacop/scoped_env.rb +25 -13
 - data/lib/schemacop/v2.rb +26 -0
 - data/lib/schemacop/{caster.rb → v2/caster.rb} +16 -2
 - data/lib/schemacop/{collector.rb → v2/collector.rb} +5 -2
 - data/lib/schemacop/{dupper.rb → v2/dupper.rb} +1 -1
 - data/lib/schemacop/{field_node.rb → v2/field_node.rb} +4 -3
 - data/lib/schemacop/v2/node.rb +142 -0
 - data/lib/schemacop/{node_resolver.rb → v2/node_resolver.rb} +1 -1
 - data/lib/schemacop/v2/node_supporting_field.rb +70 -0
 - data/lib/schemacop/{node_supporting_type.rb → v2/node_supporting_type.rb} +14 -11
 - data/lib/schemacop/{node_with_block.rb → v2/node_with_block.rb} +3 -2
 - data/lib/schemacop/v2/root_node.rb +6 -0
 - data/lib/schemacop/v2/validator/array_validator.rb +32 -0
 - data/lib/schemacop/{validator → v2/validator}/boolean_validator.rb +1 -1
 - data/lib/schemacop/v2/validator/float_validator.rb +7 -0
 - data/lib/schemacop/v2/validator/hash_validator.rb +37 -0
 - data/lib/schemacop/v2/validator/integer_validator.rb +7 -0
 - data/lib/schemacop/{validator → v2/validator}/nil_validator.rb +1 -1
 - data/lib/schemacop/v2/validator/number_validator.rb +21 -0
 - data/lib/schemacop/v2/validator/object_validator.rb +29 -0
 - data/lib/schemacop/v2/validator/string_validator.rb +39 -0
 - data/lib/schemacop/{validator → v2/validator}/symbol_validator.rb +1 -1
 - data/lib/schemacop/v3.rb +45 -0
 - data/lib/schemacop/v3/all_of_node.rb +27 -0
 - data/lib/schemacop/v3/any_of_node.rb +28 -0
 - data/lib/schemacop/v3/array_node.rb +218 -0
 - data/lib/schemacop/v3/boolean_node.rb +16 -0
 - data/lib/schemacop/v3/combination_node.rb +45 -0
 - data/lib/schemacop/v3/context.rb +17 -0
 - data/lib/schemacop/v3/dsl_scope.rb +46 -0
 - data/lib/schemacop/v3/global_context.rb +114 -0
 - data/lib/schemacop/v3/hash_node.rb +256 -0
 - data/lib/schemacop/v3/integer_node.rb +13 -0
 - data/lib/schemacop/v3/is_not_node.rb +32 -0
 - data/lib/schemacop/v3/node.rb +215 -0
 - data/lib/schemacop/v3/node_registry.rb +49 -0
 - data/lib/schemacop/v3/number_node.rb +18 -0
 - data/lib/schemacop/v3/numeric_node.rb +76 -0
 - data/lib/schemacop/v3/object_node.rb +40 -0
 - data/lib/schemacop/v3/one_of_node.rb +28 -0
 - data/lib/schemacop/v3/reference_node.rb +49 -0
 - data/lib/schemacop/v3/result.rb +58 -0
 - data/lib/schemacop/v3/string_node.rb +124 -0
 - data/lib/schemacop/v3/symbol_node.rb +13 -0
 - data/schemacop.gemspec +24 -27
 - data/test/lib/test_helper.rb +152 -0
 - data/test/schemas/nested/group.rb +6 -0
 - data/test/schemas/user.rb +7 -0
 - data/test/unit/schemacop/v2/casting_test.rb +120 -0
 - data/test/unit/schemacop/v2/collector_test.rb +47 -0
 - data/test/unit/schemacop/v2/custom_check_test.rb +95 -0
 - data/test/unit/schemacop/v2/custom_if_test.rb +97 -0
 - data/test/unit/schemacop/v2/defaults_test.rb +95 -0
 - data/test/unit/schemacop/v2/empty_test.rb +16 -0
 - data/test/unit/schemacop/v2/nil_dis_allow_test.rb +43 -0
 - data/test/unit/schemacop/v2/node_resolver_test.rb +28 -0
 - data/test/unit/schemacop/v2/short_forms_test.rb +351 -0
 - data/test/unit/schemacop/v2/types_test.rb +88 -0
 - data/test/unit/schemacop/v2/validator_array_test.rb +99 -0
 - data/test/unit/schemacop/v2/validator_boolean_test.rb +17 -0
 - data/test/unit/schemacop/v2/validator_float_test.rb +59 -0
 - data/test/unit/schemacop/v2/validator_hash_test.rb +95 -0
 - data/test/unit/schemacop/v2/validator_integer_test.rb +48 -0
 - data/test/unit/schemacop/v2/validator_nil_test.rb +15 -0
 - data/test/unit/schemacop/v2/validator_number_test.rb +62 -0
 - data/test/unit/schemacop/v2/validator_object_test.rb +141 -0
 - data/test/unit/schemacop/v2/validator_string_test.rb +78 -0
 - data/test/unit/schemacop/v2/validator_symbol_test.rb +18 -0
 - data/test/unit/schemacop/v3/all_of_node_test.rb +198 -0
 - data/test/unit/schemacop/v3/any_of_node_test.rb +218 -0
 - data/test/unit/schemacop/v3/array_node_test.rb +815 -0
 - data/test/unit/schemacop/v3/boolean_node_test.rb +126 -0
 - data/test/unit/schemacop/v3/global_context_test.rb +164 -0
 - data/test/unit/schemacop/v3/hash_node_test.rb +884 -0
 - data/test/unit/schemacop/v3/integer_node_test.rb +323 -0
 - data/test/unit/schemacop/v3/is_not_node_test.rb +173 -0
 - data/test/unit/schemacop/v3/node_test.rb +148 -0
 - data/test/unit/schemacop/v3/number_node_test.rb +292 -0
 - data/test/unit/schemacop/v3/object_node_test.rb +170 -0
 - data/test/unit/schemacop/v3/one_of_node_test.rb +187 -0
 - data/test/unit/schemacop/v3/reference_node_test.rb +351 -0
 - data/test/unit/schemacop/v3/string_node_test.rb +334 -0
 - data/test/unit/schemacop/v3/symbol_node_test.rb +75 -0
 - metadata +152 -145
 - data/doc/Schemacop.html +0 -146
 - data/doc/Schemacop/ArrayValidator.html +0 -329
 - data/doc/Schemacop/BooleanValidator.html +0 -145
 - data/doc/Schemacop/Caster.html +0 -379
 - data/doc/Schemacop/Collector.html +0 -787
 - data/doc/Schemacop/Dupper.html +0 -214
 - data/doc/Schemacop/Exceptions.html +0 -115
 - data/doc/Schemacop/Exceptions/InvalidSchemaError.html +0 -124
 - data/doc/Schemacop/Exceptions/ValidationError.html +0 -124
 - data/doc/Schemacop/FieldNode.html +0 -421
 - data/doc/Schemacop/FloatValidator.html +0 -158
 - data/doc/Schemacop/HashValidator.html +0 -293
 - data/doc/Schemacop/IntegerValidator.html +0 -158
 - data/doc/Schemacop/NilValidator.html +0 -145
 - data/doc/Schemacop/Node.html +0 -1438
 - data/doc/Schemacop/NodeResolver.html +0 -258
 - data/doc/Schemacop/NodeSupportingField.html +0 -590
 - data/doc/Schemacop/NodeSupportingType.html +0 -612
 - data/doc/Schemacop/NodeWithBlock.html +0 -289
 - data/doc/Schemacop/NumberValidator.html +0 -232
 - data/doc/Schemacop/ObjectValidator.html +0 -298
 - data/doc/Schemacop/RootNode.html +0 -171
 - data/doc/Schemacop/Schema.html +0 -699
 - data/doc/Schemacop/StringValidator.html +0 -295
 - data/doc/Schemacop/SymbolValidator.html +0 -145
 - data/doc/ScopedEnv.html +0 -351
 - data/doc/_index.html +0 -379
 - data/doc/class_list.html +0 -51
 - data/doc/css/common.css +0 -1
 - data/doc/css/full_list.css +0 -58
 - data/doc/css/style.css +0 -496
 - data/doc/file.README.html +0 -833
 - data/doc/file_list.html +0 -56
 - data/doc/frames.html +0 -17
 - data/doc/index.html +0 -833
 - data/doc/inheritance.graphml +0 -524
 - data/doc/inheritance.pdf +0 -825
 - data/doc/js/app.js +0 -303
 - data/doc/js/full_list.js +0 -216
 - data/doc/js/jquery.js +0 -4
 - data/doc/method_list.html +0 -587
 - data/doc/top-level-namespace.html +0 -112
 - data/lib/schemacop/node.rb +0 -139
 - data/lib/schemacop/node_supporting_field.rb +0 -58
 - data/lib/schemacop/root_node.rb +0 -4
 - data/lib/schemacop/validator/array_validator.rb +0 -30
 - data/lib/schemacop/validator/float_validator.rb +0 -5
 - data/lib/schemacop/validator/hash_validator.rb +0 -35
 - data/lib/schemacop/validator/integer_validator.rb +0 -5
 - data/lib/schemacop/validator/number_validator.rb +0 -19
 - data/lib/schemacop/validator/object_validator.rb +0 -27
 - data/lib/schemacop/validator/string_validator.rb +0 -37
 - data/test/casting_test.rb +0 -90
 - data/test/collector_test.rb +0 -45
 - data/test/custom_check_test.rb +0 -93
 - data/test/custom_if_test.rb +0 -95
 - data/test/defaults_test.rb +0 -93
 - data/test/empty_test.rb +0 -14
 - data/test/nil_dis_allow_test.rb +0 -41
 - data/test/node_resolver_test.rb +0 -26
 - data/test/short_forms_test.rb +0 -349
 - data/test/test_helper.rb +0 -13
 - data/test/types_test.rb +0 -84
 - data/test/validator_array_test.rb +0 -97
 - data/test/validator_boolean_test.rb +0 -15
 - data/test/validator_float_test.rb +0 -57
 - data/test/validator_hash_test.rb +0 -93
 - data/test/validator_integer_test.rb +0 -46
 - data/test/validator_nil_test.rb +0 -13
 - data/test/validator_number_test.rb +0 -60
 - data/test/validator_object_test.rb +0 -139
 - data/test/validator_string_test.rb +0 -76
 - data/test/validator_symbol_test.rb +0 -16
 
| 
         @@ -0,0 +1,46 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Schemacop
         
     | 
| 
      
 2 
     | 
    
         
            +
              module V3
         
     | 
| 
      
 3 
     | 
    
         
            +
                class DslScope
         
     | 
| 
      
 4 
     | 
    
         
            +
                  EXP_NAME = /^dsl_([a-z_]+)([?!])?$/.freeze
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  def initialize(node)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    @node = node
         
     | 
| 
      
 8 
     | 
    
         
            +
                    @with_name = @node.class.supports_children_options[:name]
         
     | 
| 
      
 9 
     | 
    
         
            +
                  end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  def method_missing(name, *args, **options, &block)
         
     | 
| 
      
 12 
     | 
    
         
            +
                    match = EXP_NAME.match(name)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    return super unless match
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                    base_name, req_optional = match.captures
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                    if req_optional == '!'
         
     | 
| 
      
 18 
     | 
    
         
            +
                      options[:required] = true
         
     | 
| 
      
 19 
     | 
    
         
            +
                    elsif req_optional == '?'
         
     | 
| 
      
 20 
     | 
    
         
            +
                      options[:required] = false
         
     | 
| 
      
 21 
     | 
    
         
            +
                    end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                    options[:parent] = @node
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                    if (klass = NodeRegistry.by_short_name(base_name))
         
     | 
| 
      
 26 
     | 
    
         
            +
                      if @with_name
         
     | 
| 
      
 27 
     | 
    
         
            +
                        options[:name] = args.shift
         
     | 
| 
      
 28 
     | 
    
         
            +
                      end
         
     | 
| 
      
 29 
     | 
    
         
            +
                      node = klass.create(*args, **options, &block)
         
     | 
| 
      
 30 
     | 
    
         
            +
                      @node.add_child node
         
     | 
| 
      
 31 
     | 
    
         
            +
                      return node
         
     | 
| 
      
 32 
     | 
    
         
            +
                    else
         
     | 
| 
      
 33 
     | 
    
         
            +
                      return super
         
     | 
| 
      
 34 
     | 
    
         
            +
                    end
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  def respond_to_missing?(name, *args)
         
     | 
| 
      
 38 
     | 
    
         
            +
                    match = EXP_NAME.match(name)
         
     | 
| 
      
 39 
     | 
    
         
            +
                    return super unless match
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                    base_name, _req_optional = match.captures
         
     | 
| 
      
 42 
     | 
    
         
            +
                    return NodeRegistry.by_short_name(base_name).present? || super
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
              end
         
     | 
| 
      
 46 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,114 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Schemacop
         
     | 
| 
      
 2 
     | 
    
         
            +
              module V3
         
     | 
| 
      
 3 
     | 
    
         
            +
                class GlobalContext < Context
         
     | 
| 
      
 4 
     | 
    
         
            +
                  DSL_METHODS = %i[schema].freeze
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  def self.instance
         
     | 
| 
      
 7 
     | 
    
         
            +
                    @instance ||= new
         
     | 
| 
      
 8 
     | 
    
         
            +
                  end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  def self.eager_load!
         
     | 
| 
      
 11 
     | 
    
         
            +
                    instance.eager_load!
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def self.schemas
         
     | 
| 
      
 15 
     | 
    
         
            +
                    instance.schemas
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  def self.schema_for(path)
         
     | 
| 
      
 19 
     | 
    
         
            +
                    instance.schema_for(path)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  def schema(type = :hash, **options, &block)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    @current_schemas << Node.create(type, **options, &block)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  def schema_for(path)
         
     | 
| 
      
 27 
     | 
    
         
            +
                    path = path.to_sym
         
     | 
| 
      
 28 
     | 
    
         
            +
                    load_schema(path) unless @eager_loaded
         
     | 
| 
      
 29 
     | 
    
         
            +
                    @schemas[path]
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                  def eager_load!
         
     | 
| 
      
 33 
     | 
    
         
            +
                    @schemas = {}
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                    fail "Global context can't be eager loaded more than once." if @eager_loaded
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                    Schemacop.load_paths.each do |load_path|
         
     | 
| 
      
 38 
     | 
    
         
            +
                      Dir.glob(File.join(load_path, '**', '*.rb')).sort.each do |file|
         
     | 
| 
      
 39 
     | 
    
         
            +
                        load_file(file, load_path)
         
     | 
| 
      
 40 
     | 
    
         
            +
                      end
         
     | 
| 
      
 41 
     | 
    
         
            +
                    end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                    @eager_loaded = true
         
     | 
| 
      
 44 
     | 
    
         
            +
                  end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                  private
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                  def initialize
         
     | 
| 
      
 49 
     | 
    
         
            +
                    super
         
     | 
| 
      
 50 
     | 
    
         
            +
                    @schemas = {}
         
     | 
| 
      
 51 
     | 
    
         
            +
                    @load_paths_by_schemas = {}
         
     | 
| 
      
 52 
     | 
    
         
            +
                    @eager_loaded = false
         
     | 
| 
      
 53 
     | 
    
         
            +
                    @current_virtual_path = nil
         
     | 
| 
      
 54 
     | 
    
         
            +
                  end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                  def path_for(virtual_path)
         
     | 
| 
      
 57 
     | 
    
         
            +
                    "#{virtual_path.to_s.underscore}.rb"
         
     | 
| 
      
 58 
     | 
    
         
            +
                  end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                  def virtual_path_for(path, load_path)
         
     | 
| 
      
 61 
     | 
    
         
            +
                    Pathname.new(path).relative_path_from(load_path).to_s.underscore.gsub(/\.rb$/, '').to_sym
         
     | 
| 
      
 62 
     | 
    
         
            +
                  end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                  def load_schema(virtual_path)
         
     | 
| 
      
 65 
     | 
    
         
            +
                    path = path_for(virtual_path)
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                    @schemas = schemas.except(virtual_path).freeze
         
     | 
| 
      
 68 
     | 
    
         
            +
                    @load_paths_by_schemas = @load_paths_by_schemas.except(virtual_path)
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                    Schemacop.load_paths.each do |load_path|
         
     | 
| 
      
 71 
     | 
    
         
            +
                      path_in_load_path = File.join(load_path, path)
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                      if File.exist?(path_in_load_path)
         
     | 
| 
      
 74 
     | 
    
         
            +
                        load_file(path_in_load_path, load_path)
         
     | 
| 
      
 75 
     | 
    
         
            +
                      end
         
     | 
| 
      
 76 
     | 
    
         
            +
                    end
         
     | 
| 
      
 77 
     | 
    
         
            +
                  end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                  def load_file(path, load_path)
         
     | 
| 
      
 80 
     | 
    
         
            +
                    return false unless File.exist?(path)
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                    # Determine virtual path
         
     | 
| 
      
 83 
     | 
    
         
            +
                    virtual_path = virtual_path_for(path, load_path)
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                    # Run file and collect schemas
         
     | 
| 
      
 86 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 87 
     | 
    
         
            +
                      @current_schemas = []
         
     | 
| 
      
 88 
     | 
    
         
            +
                      env = ScopedEnv.new(self, DSL_METHODS)
         
     | 
| 
      
 89 
     | 
    
         
            +
                      env.instance_eval IO.read(path)
         
     | 
| 
      
 90 
     | 
    
         
            +
                    rescue StandardError => e
         
     | 
| 
      
 91 
     | 
    
         
            +
                      fail "Could not load schema #{path.inspect}: #{e.message}"
         
     | 
| 
      
 92 
     | 
    
         
            +
                    end
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
                    # Load schemas
         
     | 
| 
      
 95 
     | 
    
         
            +
                    case @current_schemas.size
         
     | 
| 
      
 96 
     | 
    
         
            +
                    when 0
         
     | 
| 
      
 97 
     | 
    
         
            +
                      fail "Schema #{path.inspect} does not define any schema."
         
     | 
| 
      
 98 
     | 
    
         
            +
                    when 1
         
     | 
| 
      
 99 
     | 
    
         
            +
                      if @schemas.include?(virtual_path)
         
     | 
| 
      
 100 
     | 
    
         
            +
                        fail "Schema #{virtual_path.to_s.inspect} is defined in both load paths "\
         
     | 
| 
      
 101 
     | 
    
         
            +
                             "#{@load_paths_by_schemas[virtual_path].inspect} and #{load_path.inspect}."
         
     | 
| 
      
 102 
     | 
    
         
            +
                      end
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                      @load_paths_by_schemas[virtual_path] = load_path
         
     | 
| 
      
 105 
     | 
    
         
            +
                      @schemas = @schemas.merge(virtual_path => @current_schemas.first)
         
     | 
| 
      
 106 
     | 
    
         
            +
                    else
         
     | 
| 
      
 107 
     | 
    
         
            +
                      fail "Schema #{path.inspect} defines multiple schemas."
         
     | 
| 
      
 108 
     | 
    
         
            +
                    end
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
                    return true
         
     | 
| 
      
 111 
     | 
    
         
            +
                  end
         
     | 
| 
      
 112 
     | 
    
         
            +
                end
         
     | 
| 
      
 113 
     | 
    
         
            +
              end
         
     | 
| 
      
 114 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,256 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Schemacop
         
     | 
| 
      
 2 
     | 
    
         
            +
              module V3
         
     | 
| 
      
 3 
     | 
    
         
            +
                class HashNode < Node
         
     | 
| 
      
 4 
     | 
    
         
            +
                  ATTRIBUTES = %i[
         
     | 
| 
      
 5 
     | 
    
         
            +
                    type
         
     | 
| 
      
 6 
     | 
    
         
            +
                    min_properties
         
     | 
| 
      
 7 
     | 
    
         
            +
                    max_properties
         
     | 
| 
      
 8 
     | 
    
         
            +
                    dependencies
         
     | 
| 
      
 9 
     | 
    
         
            +
                    property_names
         
     | 
| 
      
 10 
     | 
    
         
            +
                  ].freeze
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  supports_children(name: true)
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def self.allowed_options
         
     | 
| 
      
 15 
     | 
    
         
            +
                    super + ATTRIBUTES - %i[dependencies] + %i[additional_properties]
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  def self.dsl_methods
         
     | 
| 
      
 19 
     | 
    
         
            +
                    super + NodeRegistry.dsl_methods(true) + %i[dsl_dep dsl_add]
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  def add_child(node)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    unless node.name
         
     | 
| 
      
 24 
     | 
    
         
            +
                      fail Exceptions::InvalidSchemaError, 'Child nodes must have a name.'
         
     | 
| 
      
 25 
     | 
    
         
            +
                    end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                    @properties[node.name] = node
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  def dsl_add(type, **options, &block)
         
     | 
| 
      
 31 
     | 
    
         
            +
                    if @options[:additional_properties].is_a?(Node)
         
     | 
| 
      
 32 
     | 
    
         
            +
                      fail Exceptions::InvalidSchemaError, 'You can only use "add" once to specify additional properties.'
         
     | 
| 
      
 33 
     | 
    
         
            +
                    end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                    @options[:additional_properties] = create(type, **options, &block)
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                  def dsl_dep(source, *targets, **_kwargs)
         
     | 
| 
      
 39 
     | 
    
         
            +
                    @options[:dependencies] ||= {}
         
     | 
| 
      
 40 
     | 
    
         
            +
                    @options[:dependencies][source] = targets
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                  def as_json
         
     | 
| 
      
 44 
     | 
    
         
            +
                    properties = {}
         
     | 
| 
      
 45 
     | 
    
         
            +
                    pattern_properties = {}
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                    @properties.each do |name, property|
         
     | 
| 
      
 48 
     | 
    
         
            +
                      if name.is_a?(Regexp)
         
     | 
| 
      
 49 
     | 
    
         
            +
                        pattern_properties[name] = property
         
     | 
| 
      
 50 
     | 
    
         
            +
                      else
         
     | 
| 
      
 51 
     | 
    
         
            +
                        properties[name] = property
         
     | 
| 
      
 52 
     | 
    
         
            +
                      end
         
     | 
| 
      
 53 
     | 
    
         
            +
                    end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                    json = {}
         
     | 
| 
      
 56 
     | 
    
         
            +
                    json[:properties] = Hash[properties.values.map { |p| [p.name, p.as_json] }] if properties.any?
         
     | 
| 
      
 57 
     | 
    
         
            +
                    json[:patternProperties] = Hash[pattern_properties.values.map { |p| [sanitize_exp(p.name), p.as_json] }] if pattern_properties.any?
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                    # In schemacop, by default, additional properties are not allowed,
         
     | 
| 
      
 60 
     | 
    
         
            +
                    # the users explicitly need to enable additional properties
         
     | 
| 
      
 61 
     | 
    
         
            +
                    if options[:additional_properties] == true
         
     | 
| 
      
 62 
     | 
    
         
            +
                      json[:additionalProperties] = true
         
     | 
| 
      
 63 
     | 
    
         
            +
                    elsif options[:additional_properties].is_a?(Node)
         
     | 
| 
      
 64 
     | 
    
         
            +
                      json[:additionalProperties] = options[:additional_properties].as_json
         
     | 
| 
      
 65 
     | 
    
         
            +
                    else
         
     | 
| 
      
 66 
     | 
    
         
            +
                      json[:additionalProperties] = false
         
     | 
| 
      
 67 
     | 
    
         
            +
                    end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                    required_properties = @properties.values.select(&:required?).map(&:name)
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                    if required_properties.any?
         
     | 
| 
      
 72 
     | 
    
         
            +
                      json[:required] = required_properties
         
     | 
| 
      
 73 
     | 
    
         
            +
                    end
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                    return process_json(ATTRIBUTES, json)
         
     | 
| 
      
 76 
     | 
    
         
            +
                  end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                  def sanitize_exp(exp)
         
     | 
| 
      
 79 
     | 
    
         
            +
                    exp = exp.to_s
         
     | 
| 
      
 80 
     | 
    
         
            +
                    if exp.start_with?('(?-mix:')
         
     | 
| 
      
 81 
     | 
    
         
            +
                      exp = exp.to_s.gsub(/^\(\?-mix:/, '').gsub(/\)$/, '')
         
     | 
| 
      
 82 
     | 
    
         
            +
                    end
         
     | 
| 
      
 83 
     | 
    
         
            +
                    return exp
         
     | 
| 
      
 84 
     | 
    
         
            +
                  end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                  def allowed_types
         
     | 
| 
      
 87 
     | 
    
         
            +
                    { Hash => :object }
         
     | 
| 
      
 88 
     | 
    
         
            +
                  end
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                  def _validate(data, result: Result.new)
         
     | 
| 
      
 91 
     | 
    
         
            +
                    super_data = super
         
     | 
| 
      
 92 
     | 
    
         
            +
                    return if super_data.nil?
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
                    original_data_hash = super_data.dup
         
     | 
| 
      
 95 
     | 
    
         
            +
                    data_hash = super_data.with_indifferent_access
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                    if original_data_hash.size != data_hash.size
         
     | 
| 
      
 98 
     | 
    
         
            +
                      ambiguous_properties = original_data_hash.keys - data_hash.keys
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
                      result.error "Has #{ambiguous_properties.size} ambiguous properties: #{ambiguous_properties}."
         
     | 
| 
      
 101 
     | 
    
         
            +
                    end
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                    # Validate min_properties #
         
     | 
| 
      
 104 
     | 
    
         
            +
                    if options[:min_properties] && data_hash.size < options[:min_properties]
         
     | 
| 
      
 105 
     | 
    
         
            +
                      result.error "Has #{data_hash.size} properties but needs at least #{options[:min_properties]}."
         
     | 
| 
      
 106 
     | 
    
         
            +
                    end
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                    # Validate max_properties #
         
     | 
| 
      
 109 
     | 
    
         
            +
                    if options[:max_properties] && data_hash.size > options[:max_properties]
         
     | 
| 
      
 110 
     | 
    
         
            +
                      result.error "Has #{data_hash.size} properties but needs at most #{options[:max_properties]}."
         
     | 
| 
      
 111 
     | 
    
         
            +
                    end
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
                    # Validate specified properties #
         
     | 
| 
      
 114 
     | 
    
         
            +
                    @properties.each_value do |node|
         
     | 
| 
      
 115 
     | 
    
         
            +
                      result.in_path(node.name) do
         
     | 
| 
      
 116 
     | 
    
         
            +
                        next if node.name.is_a?(Regexp)
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
                        node._validate(data_hash[node.name], result: result)
         
     | 
| 
      
 119 
     | 
    
         
            +
                      end
         
     | 
| 
      
 120 
     | 
    
         
            +
                    end
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                    # Validate additional properties #
         
     | 
| 
      
 123 
     | 
    
         
            +
                    specified_properties = @properties.keys.to_set
         
     | 
| 
      
 124 
     | 
    
         
            +
                    additional_properties = data_hash.reject { |k, _v| specified_properties.include?(k.to_s) }
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
                    property_patterns = {}
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
                    @properties.each_value do |property|
         
     | 
| 
      
 129 
     | 
    
         
            +
                      if property.name.is_a?(Regexp)
         
     | 
| 
      
 130 
     | 
    
         
            +
                        property_patterns[property.name] = property
         
     | 
| 
      
 131 
     | 
    
         
            +
                      end
         
     | 
| 
      
 132 
     | 
    
         
            +
                    end
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
                    property_names = options[:property_names]
         
     | 
| 
      
 135 
     | 
    
         
            +
                    property_names = Regexp.compile(property_names) if property_names
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
                    additional_properties.each do |name, additional_property|
         
     | 
| 
      
 138 
     | 
    
         
            +
                      if property_names && !property_names.match?(name)
         
     | 
| 
      
 139 
     | 
    
         
            +
                        result.error "Property name #{name.inspect} does not match #{options[:property_names].inspect}."
         
     | 
| 
      
 140 
     | 
    
         
            +
                      end
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
                      if options[:additional_properties].blank?
         
     | 
| 
      
 143 
     | 
    
         
            +
                        match = property_patterns.keys.find { |p| p.match?(name.to_s) }
         
     | 
| 
      
 144 
     | 
    
         
            +
                        if match
         
     | 
| 
      
 145 
     | 
    
         
            +
                          result.in_path(name) do
         
     | 
| 
      
 146 
     | 
    
         
            +
                            property_patterns[match]._validate(additional_property, result: result)
         
     | 
| 
      
 147 
     | 
    
         
            +
                          end
         
     | 
| 
      
 148 
     | 
    
         
            +
                        else
         
     | 
| 
      
 149 
     | 
    
         
            +
                          result.error "Obsolete property #{name.to_s.inspect}."
         
     | 
| 
      
 150 
     | 
    
         
            +
                        end
         
     | 
| 
      
 151 
     | 
    
         
            +
                      elsif options[:additional_properties].is_a?(Node)
         
     | 
| 
      
 152 
     | 
    
         
            +
                        result.in_path(name) do
         
     | 
| 
      
 153 
     | 
    
         
            +
                          options[:additional_properties]._validate(additional_property, result: result)
         
     | 
| 
      
 154 
     | 
    
         
            +
                        end
         
     | 
| 
      
 155 
     | 
    
         
            +
                      end
         
     | 
| 
      
 156 
     | 
    
         
            +
                    end
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
                    # Validate dependencies #
         
     | 
| 
      
 159 
     | 
    
         
            +
                    options[:dependencies]&.each do |source, targets|
         
     | 
| 
      
 160 
     | 
    
         
            +
                      targets.each do |target|
         
     | 
| 
      
 161 
     | 
    
         
            +
                        if data_hash[source].present? && data_hash[target].blank?
         
     | 
| 
      
 162 
     | 
    
         
            +
                          result.error "Missing property #{target.to_s.inspect} because #{source.to_s.inspect} is given."
         
     | 
| 
      
 163 
     | 
    
         
            +
                        end
         
     | 
| 
      
 164 
     | 
    
         
            +
                      end
         
     | 
| 
      
 165 
     | 
    
         
            +
                    end
         
     | 
| 
      
 166 
     | 
    
         
            +
                  end
         
     | 
| 
      
 167 
     | 
    
         
            +
             
     | 
| 
      
 168 
     | 
    
         
            +
                  def children
         
     | 
| 
      
 169 
     | 
    
         
            +
                    @properties.values
         
     | 
| 
      
 170 
     | 
    
         
            +
                  end
         
     | 
| 
      
 171 
     | 
    
         
            +
             
     | 
| 
      
 172 
     | 
    
         
            +
                  def cast(data)
         
     | 
| 
      
 173 
     | 
    
         
            +
                    result = {}.with_indifferent_access
         
     | 
| 
      
 174 
     | 
    
         
            +
                    data ||= default
         
     | 
| 
      
 175 
     | 
    
         
            +
                    return nil if data.nil?
         
     | 
| 
      
 176 
     | 
    
         
            +
             
     | 
| 
      
 177 
     | 
    
         
            +
                    original_data_hash = data.dup
         
     | 
| 
      
 178 
     | 
    
         
            +
                    data_hash = data.with_indifferent_access
         
     | 
| 
      
 179 
     | 
    
         
            +
             
     | 
| 
      
 180 
     | 
    
         
            +
                    if original_data_hash.size != data_hash.size
         
     | 
| 
      
 181 
     | 
    
         
            +
                      ambiguous_properties = original_data_hash.keys - data_hash.keys
         
     | 
| 
      
 182 
     | 
    
         
            +
             
     | 
| 
      
 183 
     | 
    
         
            +
                      result.error "Has #{ambiguous_properties.size} ambiguous properties: #{ambiguous_properties}."
         
     | 
| 
      
 184 
     | 
    
         
            +
                    end
         
     | 
| 
      
 185 
     | 
    
         
            +
             
     | 
| 
      
 186 
     | 
    
         
            +
                    property_patterns = {}
         
     | 
| 
      
 187 
     | 
    
         
            +
             
     | 
| 
      
 188 
     | 
    
         
            +
                    @properties.each_value do |prop|
         
     | 
| 
      
 189 
     | 
    
         
            +
                      if prop.name.is_a?(Regexp)
         
     | 
| 
      
 190 
     | 
    
         
            +
                        property_patterns[prop.name] = prop
         
     | 
| 
      
 191 
     | 
    
         
            +
                        next
         
     | 
| 
      
 192 
     | 
    
         
            +
                      end
         
     | 
| 
      
 193 
     | 
    
         
            +
             
     | 
| 
      
 194 
     | 
    
         
            +
                      result[prop.name] = prop.cast(data_hash[prop.name])
         
     | 
| 
      
 195 
     | 
    
         
            +
             
     | 
| 
      
 196 
     | 
    
         
            +
                      if result[prop.name].nil? && !data_hash.include?(prop.name)
         
     | 
| 
      
 197 
     | 
    
         
            +
                        result.delete(prop.name)
         
     | 
| 
      
 198 
     | 
    
         
            +
                      end
         
     | 
| 
      
 199 
     | 
    
         
            +
                    end
         
     | 
| 
      
 200 
     | 
    
         
            +
             
     | 
| 
      
 201 
     | 
    
         
            +
                    # Handle regex properties
         
     | 
| 
      
 202 
     | 
    
         
            +
                    specified_properties = @properties.keys.to_set
         
     | 
| 
      
 203 
     | 
    
         
            +
                    additional_properties = data_hash.reject { |k, _v| specified_properties.include?(k.to_s.to_sym) }
         
     | 
| 
      
 204 
     | 
    
         
            +
             
     | 
| 
      
 205 
     | 
    
         
            +
                    if additional_properties.any? && property_patterns.any?
         
     | 
| 
      
 206 
     | 
    
         
            +
                      additional_properties.each do |name, additional_property|
         
     | 
| 
      
 207 
     | 
    
         
            +
                        match_key = property_patterns.keys.find { |p| p.match?(name.to_s) }
         
     | 
| 
      
 208 
     | 
    
         
            +
                        match = property_patterns[match_key]
         
     | 
| 
      
 209 
     | 
    
         
            +
                        result[name] = match.cast(additional_property)
         
     | 
| 
      
 210 
     | 
    
         
            +
                      end
         
     | 
| 
      
 211 
     | 
    
         
            +
                    end
         
     | 
| 
      
 212 
     | 
    
         
            +
             
     | 
| 
      
 213 
     | 
    
         
            +
                    # Handle additional properties
         
     | 
| 
      
 214 
     | 
    
         
            +
                    if options[:additional_properties] == true
         
     | 
| 
      
 215 
     | 
    
         
            +
                      result = data_hash.merge(result)
         
     | 
| 
      
 216 
     | 
    
         
            +
                    elsif options[:additional_properties].is_a?(Node)
         
     | 
| 
      
 217 
     | 
    
         
            +
                      specified_properties = @properties.keys.to_set
         
     | 
| 
      
 218 
     | 
    
         
            +
                      additional_properties = data_hash.reject { |k, _v| specified_properties.include?(k.to_s.to_sym) }
         
     | 
| 
      
 219 
     | 
    
         
            +
                      if additional_properties.any?
         
     | 
| 
      
 220 
     | 
    
         
            +
                        additional_properties_result = {}
         
     | 
| 
      
 221 
     | 
    
         
            +
                        additional_properties.each do |key, value|
         
     | 
| 
      
 222 
     | 
    
         
            +
                          additional_properties_result[key] = options[:additional_properties].cast(value)
         
     | 
| 
      
 223 
     | 
    
         
            +
                        end
         
     | 
| 
      
 224 
     | 
    
         
            +
                        result = additional_properties_result.merge(result)
         
     | 
| 
      
 225 
     | 
    
         
            +
                      end
         
     | 
| 
      
 226 
     | 
    
         
            +
                    end
         
     | 
| 
      
 227 
     | 
    
         
            +
             
     | 
| 
      
 228 
     | 
    
         
            +
                    return result
         
     | 
| 
      
 229 
     | 
    
         
            +
                  end
         
     | 
| 
      
 230 
     | 
    
         
            +
             
     | 
| 
      
 231 
     | 
    
         
            +
                  protected
         
     | 
| 
      
 232 
     | 
    
         
            +
             
     | 
| 
      
 233 
     | 
    
         
            +
                  def init
         
     | 
| 
      
 234 
     | 
    
         
            +
                    @properties = {}
         
     | 
| 
      
 235 
     | 
    
         
            +
                    @options[:type] = :object
         
     | 
| 
      
 236 
     | 
    
         
            +
                    unless @options[:additional_properties].nil? || @options[:additional_properties].is_a?(TrueClass) || @options[:additional_properties].is_a?(FalseClass)
         
     | 
| 
      
 237 
     | 
    
         
            +
                      fail Schemacop::Exceptions::InvalidSchemaError, 'Option "additional_properties" must be a boolean value'
         
     | 
| 
      
 238 
     | 
    
         
            +
                    end
         
     | 
| 
      
 239 
     | 
    
         
            +
                  end
         
     | 
| 
      
 240 
     | 
    
         
            +
             
     | 
| 
      
 241 
     | 
    
         
            +
                  def validate_self
         
     | 
| 
      
 242 
     | 
    
         
            +
                    unless options[:min_properties].nil? || options[:min_properties].is_a?(Integer)
         
     | 
| 
      
 243 
     | 
    
         
            +
                      fail 'Option "min_properties" must be an "integer"'
         
     | 
| 
      
 244 
     | 
    
         
            +
                    end
         
     | 
| 
      
 245 
     | 
    
         
            +
             
     | 
| 
      
 246 
     | 
    
         
            +
                    unless options[:max_properties].nil? || options[:max_properties].is_a?(Integer)
         
     | 
| 
      
 247 
     | 
    
         
            +
                      fail 'Option "max_properties" must be an "integer"'
         
     | 
| 
      
 248 
     | 
    
         
            +
                    end
         
     | 
| 
      
 249 
     | 
    
         
            +
             
     | 
| 
      
 250 
     | 
    
         
            +
                    if @properties.values.any? { |p| p.name.is_a?(Regexp) && p.required? }
         
     | 
| 
      
 251 
     | 
    
         
            +
                      fail 'Pattern properties can\'t be required.'
         
     | 
| 
      
 252 
     | 
    
         
            +
                    end
         
     | 
| 
      
 253 
     | 
    
         
            +
                  end
         
     | 
| 
      
 254 
     | 
    
         
            +
                end
         
     | 
| 
      
 255 
     | 
    
         
            +
              end
         
     | 
| 
      
 256 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,32 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Schemacop
         
     | 
| 
      
 2 
     | 
    
         
            +
              module V3
         
     | 
| 
      
 3 
     | 
    
         
            +
                class IsNotNode < CombinationNode
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def type
         
     | 
| 
      
 5 
     | 
    
         
            +
                    :not
         
     | 
| 
      
 6 
     | 
    
         
            +
                  end
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def _validate(data, result:)
         
     | 
| 
      
 9 
     | 
    
         
            +
                    super_data = super
         
     | 
| 
      
 10 
     | 
    
         
            +
                    return if super_data.nil?
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                    if matches(super_data).any?
         
     | 
| 
      
 13 
     | 
    
         
            +
                      result.error "Must not match schema: #{@items.first.as_json.as_json.inspect}."
         
     | 
| 
      
 14 
     | 
    
         
            +
                    end
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  def as_json
         
     | 
| 
      
 18 
     | 
    
         
            +
                    process_json([], type => @items.first.as_json)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  def validate_self
         
     | 
| 
      
 22 
     | 
    
         
            +
                    if @items.count != 1
         
     | 
| 
      
 23 
     | 
    
         
            +
                      fail 'Node "is_not" only allows exactly one item.'
         
     | 
| 
      
 24 
     | 
    
         
            +
                    end
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  def cast(data)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    data
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
              end
         
     | 
| 
      
 32 
     | 
    
         
            +
            end
         
     |