schemacop 2.4.7 → 3.0.0.rc0
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 +2 -1
- data/CHANGELOG.md +8 -0
- data/README.md +41 -708
- data/README_V2.md +775 -0
- data/README_V3.md +683 -0
- data/Rakefile +8 -12
- data/VERSION +1 -1
- data/lib/schemacop.rb +35 -37
- 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/{node_supporting_field.rb → v2/node_supporting_field.rb} +8 -10
- data/lib/schemacop/{node_supporting_type.rb → v2/node_supporting_type.rb} +6 -3
- 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 +219 -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 +217 -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 +214 -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 +199 -0
- data/test/unit/schemacop/v3/any_of_node_test.rb +218 -0
- data/test/unit/schemacop/v3/array_node_test.rb +805 -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 +775 -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/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 -118
- 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
data/lib/schemacop/v3.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
module Schemacop
|
2
|
+
module V3
|
3
|
+
def self.register(*args)
|
4
|
+
NodeRegistry.register(*args)
|
5
|
+
end
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
# Require V3 files
|
10
|
+
require 'schemacop/v3/node_registry'
|
11
|
+
require 'schemacop/v3/dsl_scope'
|
12
|
+
require 'schemacop/v3/context'
|
13
|
+
require 'schemacop/v3/global_context'
|
14
|
+
require 'schemacop/v3/result'
|
15
|
+
require 'schemacop/v3/node'
|
16
|
+
require 'schemacop/v3/combination_node'
|
17
|
+
require 'schemacop/v3/numeric_node'
|
18
|
+
require 'schemacop/v3/all_of_node'
|
19
|
+
require 'schemacop/v3/any_of_node'
|
20
|
+
require 'schemacop/v3/array_node'
|
21
|
+
require 'schemacop/v3/boolean_node'
|
22
|
+
require 'schemacop/v3/hash_node'
|
23
|
+
require 'schemacop/v3/integer_node'
|
24
|
+
require 'schemacop/v3/is_not_node'
|
25
|
+
require 'schemacop/v3/number_node'
|
26
|
+
require 'schemacop/v3/object_node'
|
27
|
+
require 'schemacop/v3/one_of_node'
|
28
|
+
require 'schemacop/v3/reference_node'
|
29
|
+
require 'schemacop/v3/string_node'
|
30
|
+
require 'schemacop/v3/symbol_node'
|
31
|
+
|
32
|
+
# Register built-in nodes
|
33
|
+
Schemacop::V3.register :all_of, :all_of, Schemacop::V3::AllOfNode
|
34
|
+
Schemacop::V3.register :any_of, :any_of, Schemacop::V3::AnyOfNode
|
35
|
+
Schemacop::V3.register :array, :ary, Schemacop::V3::ArrayNode
|
36
|
+
Schemacop::V3.register :boolean, :boo, Schemacop::V3::BooleanNode
|
37
|
+
Schemacop::V3.register :integer, :int, Schemacop::V3::IntegerNode
|
38
|
+
Schemacop::V3.register :is_not, :is_not, Schemacop::V3::IsNotNode
|
39
|
+
Schemacop::V3.register :number, :num, Schemacop::V3::NumberNode
|
40
|
+
Schemacop::V3.register :hash, :hsh, Schemacop::V3::HashNode
|
41
|
+
Schemacop::V3.register :one_of, :one_of, Schemacop::V3::OneOfNode
|
42
|
+
Schemacop::V3.register :reference, :ref, Schemacop::V3::ReferenceNode
|
43
|
+
Schemacop::V3.register :object, :obj, Schemacop::V3::ObjectNode
|
44
|
+
Schemacop::V3.register :string, :str, Schemacop::V3::StringNode
|
45
|
+
Schemacop::V3.register :symbol, :sym, Schemacop::V3::SymbolNode
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Schemacop
|
2
|
+
module V3
|
3
|
+
class AllOfNode < CombinationNode
|
4
|
+
def type
|
5
|
+
:allOf
|
6
|
+
end
|
7
|
+
|
8
|
+
def _validate(data, result:)
|
9
|
+
super_data = super
|
10
|
+
return if super_data.nil?
|
11
|
+
|
12
|
+
if matches(super_data).size != @items.size
|
13
|
+
result.error 'Does not match all allOf conditions.'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def cast(value)
|
18
|
+
items = matches(value)
|
19
|
+
return value unless items
|
20
|
+
|
21
|
+
casted_value = value.dup
|
22
|
+
items.each { |i| casted_value = i.cast(casted_value) }
|
23
|
+
return casted_value
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Schemacop
|
2
|
+
module V3
|
3
|
+
class AnyOfNode < CombinationNode
|
4
|
+
def type
|
5
|
+
:anyOf
|
6
|
+
end
|
7
|
+
|
8
|
+
def _validate(data, result:)
|
9
|
+
super_data = super
|
10
|
+
return if super_data.nil?
|
11
|
+
|
12
|
+
match = match(super_data)
|
13
|
+
|
14
|
+
if match
|
15
|
+
match._validate(super_data, result: result)
|
16
|
+
else
|
17
|
+
result.error 'Does not match any anyOf condition.'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def validate_self
|
22
|
+
if @items.empty?
|
23
|
+
fail 'Node "any_of" makes only sense with at least 1 item.'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,219 @@
|
|
1
|
+
module Schemacop
|
2
|
+
module V3
|
3
|
+
class ArrayNode < Node
|
4
|
+
ATTRIBUTES = %i[
|
5
|
+
min_items
|
6
|
+
max_items
|
7
|
+
unique_items
|
8
|
+
].freeze
|
9
|
+
|
10
|
+
supports_children
|
11
|
+
|
12
|
+
def self.allowed_options
|
13
|
+
super + ATTRIBUTES + %i[additional_items]
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.dsl_methods
|
17
|
+
super + NodeRegistry.dsl_methods(false) + %i[dsl_add dsl_list dsl_cont]
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_reader :items
|
21
|
+
attr_accessor :list_item
|
22
|
+
attr_accessor :cont_item
|
23
|
+
|
24
|
+
def dsl_add(type, **options, &block)
|
25
|
+
if @options[:additional_items].is_a?(Node)
|
26
|
+
fail Exceptions::InvalidSchemaError, 'You can only use "add" once to specify additional items.'
|
27
|
+
end
|
28
|
+
|
29
|
+
@options[:additional_items] = create(type, **options, &block)
|
30
|
+
end
|
31
|
+
|
32
|
+
def dsl_list(type, **options, &block)
|
33
|
+
if list_item.is_a?(Node)
|
34
|
+
fail Exceptions::InvalidSchemaError, 'You can only use "list" once.'
|
35
|
+
end
|
36
|
+
|
37
|
+
@list_item = create(type, **options, &block)
|
38
|
+
end
|
39
|
+
|
40
|
+
def dsl_cont(type, **options, &block)
|
41
|
+
if cont_item.is_a?(Node)
|
42
|
+
fail Exceptions::InvalidSchemaError, 'You can only use "cont" once.'
|
43
|
+
end
|
44
|
+
|
45
|
+
@cont_item = create(type, **options, &block)
|
46
|
+
end
|
47
|
+
|
48
|
+
def add_child(node)
|
49
|
+
@items << node
|
50
|
+
end
|
51
|
+
|
52
|
+
def as_json
|
53
|
+
json = { type: :array }
|
54
|
+
|
55
|
+
if cont_item
|
56
|
+
json[:contains] = cont_item.as_json
|
57
|
+
end
|
58
|
+
|
59
|
+
if list?
|
60
|
+
json[:items] = @list_item.as_json
|
61
|
+
elsif @items.any?
|
62
|
+
json[:items] = @items.map(&:as_json)
|
63
|
+
if options[:additional_items] == true
|
64
|
+
json[:additionalItems] = true
|
65
|
+
elsif options[:additional_items].is_a?(Node)
|
66
|
+
json[:additionalItems] = options[:additional_items].as_json
|
67
|
+
else
|
68
|
+
json[:additionalItems] = false
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
return process_json(ATTRIBUTES, json)
|
73
|
+
end
|
74
|
+
|
75
|
+
def allowed_types
|
76
|
+
{ Array => :array }
|
77
|
+
end
|
78
|
+
|
79
|
+
def _validate(data, result:)
|
80
|
+
super_data = super
|
81
|
+
return if super_data.nil?
|
82
|
+
|
83
|
+
# Validate length #
|
84
|
+
length = super_data.size
|
85
|
+
|
86
|
+
if options[:min_items] && length < options[:min_items]
|
87
|
+
result.error "Array has #{length} items but needs at least #{options[:min_items]}."
|
88
|
+
end
|
89
|
+
|
90
|
+
if options[:max_items] && length > options[:max_items]
|
91
|
+
result.error "Array has #{length} items but needs at most #{options[:max_items]}."
|
92
|
+
end
|
93
|
+
|
94
|
+
if list?
|
95
|
+
# Validate list
|
96
|
+
super_data.each_with_index do |value, index|
|
97
|
+
result.in_path :"[#{index}]" do
|
98
|
+
list_item._validate(value, result: result)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
elsif items.any?
|
102
|
+
# Validate tuple
|
103
|
+
if length == items.size || (options[:additional_items] != false && length >= items.size)
|
104
|
+
items.each_with_index do |child_node, index|
|
105
|
+
value = super_data[index]
|
106
|
+
|
107
|
+
result.in_path :"[#{index}]" do
|
108
|
+
child_node._validate(value, result: result)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Validate additional items #
|
113
|
+
if options[:additional_items].is_a?(Node)
|
114
|
+
(items.size..(length - 1)).each do |index|
|
115
|
+
additional_item = super_data[index]
|
116
|
+
result.in_path :"[#{index}]" do
|
117
|
+
options[:additional_items]._validate(additional_item, result: result)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
else
|
122
|
+
result.error "Array has #{length} items but must have exactly #{items.size}."
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
if cont_item.present? && super_data.none? { |obj| item_matches?(cont_item, obj) }
|
127
|
+
result.error "At least one entry must match schema #{cont_item.as_json.inspect}."
|
128
|
+
end
|
129
|
+
|
130
|
+
# Validate uniqueness #
|
131
|
+
if options[:unique_items] && super_data.size != super_data.uniq.size
|
132
|
+
result.error 'Array has duplicate items.'
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def children
|
137
|
+
(@items + [@cont_item]).compact
|
138
|
+
end
|
139
|
+
|
140
|
+
def cast(value)
|
141
|
+
return default unless value
|
142
|
+
|
143
|
+
result = []
|
144
|
+
|
145
|
+
value.each_with_index do |value_item, index|
|
146
|
+
if cont_item.present? && item_matches?(cont_item, value_item)
|
147
|
+
result << cont_item.cast(value_item)
|
148
|
+
elsif list?
|
149
|
+
result << list_item.cast(value_item)
|
150
|
+
elsif items.any?
|
151
|
+
if options[:additional_items] != false && index >= items.size
|
152
|
+
if options[:additional_items].is_a?(Node)
|
153
|
+
result << options[:additional_items].cast(value_item)
|
154
|
+
else
|
155
|
+
result << value_item
|
156
|
+
end
|
157
|
+
else
|
158
|
+
item = item_for_data(value_item)
|
159
|
+
result << item.cast(value_item)
|
160
|
+
end
|
161
|
+
else
|
162
|
+
result << value_item
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
return result
|
167
|
+
end
|
168
|
+
|
169
|
+
protected
|
170
|
+
|
171
|
+
def list?
|
172
|
+
list_item.present?
|
173
|
+
end
|
174
|
+
|
175
|
+
def item_for_data(data, force: true)
|
176
|
+
item = children.find { |c| item_matches?(c, data) }
|
177
|
+
return item if item
|
178
|
+
return nil unless force
|
179
|
+
|
180
|
+
fail "Could not find specification for item #{data.inspect}."
|
181
|
+
end
|
182
|
+
|
183
|
+
def init
|
184
|
+
@items = []
|
185
|
+
@cont_item = nil
|
186
|
+
|
187
|
+
if options[:additional_items].nil?
|
188
|
+
options[:additional_items] = false
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def validate_self
|
193
|
+
if list? && items.any?
|
194
|
+
fail 'Can\'t use "list" and normal items.'
|
195
|
+
end
|
196
|
+
|
197
|
+
if list? && @options[:additional_items].is_a?(Node)
|
198
|
+
fail 'Can\'t use "list" and additional items.'
|
199
|
+
end
|
200
|
+
|
201
|
+
unless options[:min_items].nil? || options[:min_items].is_a?(Integer)
|
202
|
+
fail 'Option "min_items" must be an "integer"'
|
203
|
+
end
|
204
|
+
|
205
|
+
unless options[:max_items].nil? || options[:max_items].is_a?(Integer)
|
206
|
+
fail 'Option "max_items" must be an "integer"'
|
207
|
+
end
|
208
|
+
|
209
|
+
unless options[:unique_items].nil? || options[:unique_items].is_a?(TrueClass) || options[:unique_items].is_a?(FalseClass)
|
210
|
+
fail 'Option "unique_items" must be a "boolean".'
|
211
|
+
end
|
212
|
+
|
213
|
+
if options[:min_items] && options[:max_items] && options[:min_items] > options[:max_items]
|
214
|
+
fail 'Option "min_items" can\'t be greater than "max_items".'
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Schemacop
|
2
|
+
module V3
|
3
|
+
# @abstract
|
4
|
+
class CombinationNode < Node
|
5
|
+
def self.dsl_methods
|
6
|
+
super + NodeRegistry.dsl_methods(false)
|
7
|
+
end
|
8
|
+
|
9
|
+
supports_children
|
10
|
+
|
11
|
+
def init
|
12
|
+
@items = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def as_json
|
16
|
+
process_json([], type => @items.map(&:as_json))
|
17
|
+
end
|
18
|
+
|
19
|
+
def cast(value)
|
20
|
+
item = match(value)
|
21
|
+
return value unless item
|
22
|
+
|
23
|
+
return item.cast(value)
|
24
|
+
end
|
25
|
+
|
26
|
+
def add_child(node)
|
27
|
+
@items << node
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
|
32
|
+
def type
|
33
|
+
fail NotImplementedError
|
34
|
+
end
|
35
|
+
|
36
|
+
def match(data)
|
37
|
+
matches(data).first
|
38
|
+
end
|
39
|
+
|
40
|
+
def matches(data)
|
41
|
+
@items.filter { |i| item_matches?(i, data) }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Schemacop
|
2
|
+
module V3
|
3
|
+
class Context
|
4
|
+
attr_accessor :schemas
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@schemas = {}.with_indifferent_access.freeze
|
8
|
+
end
|
9
|
+
|
10
|
+
def schema(name, type = :hash, **options, &block)
|
11
|
+
@schemas = @schemas.merge(
|
12
|
+
name => Node.create(type, **options, &block)
|
13
|
+
).freeze
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -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
|