schemacop 2.4.6 → 3.0.0.rc3
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/.releaser_config +0 -1
- data/.rubocop.yml +25 -1
- data/.travis.yml +3 -1
- data/CHANGELOG.md +33 -0
- data/README.md +53 -710
- data/README_V2.md +775 -0
- data/README_V3.md +1197 -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 +25 -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} +8 -5
- data/lib/schemacop/{node_with_block.rb → v2/node_with_block.rb} +3 -2
- data/lib/schemacop/v2/root_node.rb +0 -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 +258 -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 +219 -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 +157 -150
- 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 -100
- 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,218 @@
|
|
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)
|
176
|
+
item = children.find { |c| item_matches?(c, data) }
|
177
|
+
return item if item
|
178
|
+
|
179
|
+
fail "Could not find specification for item #{data.inspect}."
|
180
|
+
end
|
181
|
+
|
182
|
+
def init
|
183
|
+
@items = []
|
184
|
+
@cont_item = nil
|
185
|
+
|
186
|
+
if options[:additional_items].nil?
|
187
|
+
options[:additional_items] = false
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def validate_self
|
192
|
+
if list? && items.any?
|
193
|
+
fail 'Can\'t use "list" and normal items.'
|
194
|
+
end
|
195
|
+
|
196
|
+
if list? && @options[:additional_items].is_a?(Node)
|
197
|
+
fail 'Can\'t use "list" and additional items.'
|
198
|
+
end
|
199
|
+
|
200
|
+
unless options[:min_items].nil? || options[:min_items].is_a?(Integer)
|
201
|
+
fail 'Option "min_items" must be an "integer"'
|
202
|
+
end
|
203
|
+
|
204
|
+
unless options[:max_items].nil? || options[:max_items].is_a?(Integer)
|
205
|
+
fail 'Option "max_items" must be an "integer"'
|
206
|
+
end
|
207
|
+
|
208
|
+
unless options[:unique_items].nil? || options[:unique_items].is_a?(TrueClass) || options[:unique_items].is_a?(FalseClass)
|
209
|
+
fail 'Option "unique_items" must be a "boolean".'
|
210
|
+
end
|
211
|
+
|
212
|
+
if options[:min_items] && options[:max_items] && options[:min_items] > options[:max_items]
|
213
|
+
fail 'Option "min_items" can\'t be greater than "max_items".'
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
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
|
@@ -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
|