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
data/Rakefile
CHANGED
@@ -18,29 +18,25 @@ task :gemspec do
|
|
18
18
|
# needs access to ActiveSupport::HashWithIndifferentAccess and expects
|
19
19
|
# behavior of that as in version 5 of ActiveSupport.
|
20
20
|
spec.add_dependency 'activesupport', '>= 4.0'
|
21
|
-
spec.add_development_dependency 'bundler'
|
21
|
+
spec.add_development_dependency 'bundler'
|
22
22
|
spec.add_development_dependency 'rake'
|
23
|
-
spec.add_development_dependency '
|
24
|
-
spec.add_development_dependency '
|
25
|
-
spec.add_development_dependency 'haml'
|
23
|
+
spec.add_development_dependency 'minitest'
|
24
|
+
spec.add_development_dependency 'minitest-reporters'
|
26
25
|
spec.add_development_dependency 'colorize'
|
27
|
-
spec.add_development_dependency '
|
28
|
-
spec.add_development_dependency 'rubocop', '0.35.1'
|
29
|
-
spec.add_development_dependency 'redcarpet'
|
26
|
+
spec.add_development_dependency 'rubocop', '0.92.0'
|
30
27
|
spec.add_development_dependency 'pry'
|
28
|
+
spec.add_development_dependency 'byebug'
|
29
|
+
spec.add_development_dependency 'simplecov', '0.21.2'
|
31
30
|
end
|
32
31
|
|
33
32
|
File.open('schemacop.gemspec', 'w') { |f| f.write(gemspec.to_ruby.strip) }
|
34
33
|
end
|
35
34
|
|
36
|
-
# rubocop: disable Lint/HandleExceptions
|
37
35
|
begin
|
38
36
|
require 'rake/testtask'
|
39
|
-
require 'ci/reporter/rake/minitest'
|
40
37
|
Rake::TestTask.new do |t|
|
41
|
-
t.pattern = 'test
|
38
|
+
t.pattern = 'test/unit/**/*_test.rb'
|
42
39
|
t.verbose = false
|
43
|
-
t.libs << 'test'
|
40
|
+
t.libs << 'test/lib'
|
44
41
|
end
|
45
|
-
rescue LoadError
|
46
42
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
3.0.0.rc3
|
data/lib/schemacop.rb
CHANGED
@@ -1,42 +1,41 @@
|
|
1
|
+
# External dependencies
|
2
|
+
require 'active_support/all'
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
# Schemacop module
|
1
6
|
module Schemacop
|
2
|
-
|
3
|
-
String => {
|
4
|
-
Integer => proc { |s| Integer(s, 10) },
|
5
|
-
Float => proc { |s| Float(s) }
|
6
|
-
},
|
7
|
-
Float => {
|
8
|
-
Integer => proc { |f| Integer(f) }
|
9
|
-
},
|
10
|
-
Integer => {
|
11
|
-
Float => proc { |f| Float(f) }
|
12
|
-
}
|
13
|
-
}
|
14
|
-
end
|
7
|
+
CONTEXT_THREAD_KEY = :schemacop_schema_context
|
15
8
|
|
16
|
-
|
17
|
-
|
18
|
-
|
9
|
+
mattr_accessor :load_paths
|
10
|
+
self.load_paths = ['app/schemas']
|
11
|
+
|
12
|
+
mattr_accessor :default_schema_version
|
13
|
+
self.default_schema_version = 3
|
19
14
|
|
15
|
+
def self.with_context(context)
|
16
|
+
prev_context = Thread.current[CONTEXT_THREAD_KEY]
|
17
|
+
Thread.current[CONTEXT_THREAD_KEY] = context
|
18
|
+
return yield
|
19
|
+
ensure
|
20
|
+
Thread.current[CONTEXT_THREAD_KEY] = prev_context
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.context
|
24
|
+
Thread.current[CONTEXT_THREAD_KEY] ||= V3::Context.new
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Load shared
|
20
29
|
require 'schemacop/scoped_env'
|
21
30
|
require 'schemacop/exceptions'
|
31
|
+
require 'schemacop/base_schema'
|
32
|
+
require 'schemacop/schema2'
|
33
|
+
require 'schemacop/schema3'
|
22
34
|
require 'schemacop/schema'
|
23
|
-
|
24
|
-
|
25
|
-
require 'schemacop/
|
26
|
-
require 'schemacop/
|
27
|
-
|
28
|
-
|
29
|
-
require 'schemacop/
|
30
|
-
require 'schemacop/node_supporting_field'
|
31
|
-
require 'schemacop/caster'
|
32
|
-
require 'schemacop/dupper'
|
33
|
-
require 'schemacop/validator/array_validator'
|
34
|
-
require 'schemacop/validator/boolean_validator'
|
35
|
-
require 'schemacop/validator/hash_validator'
|
36
|
-
require 'schemacop/validator/number_validator'
|
37
|
-
require 'schemacop/validator/integer_validator'
|
38
|
-
require 'schemacop/validator/float_validator'
|
39
|
-
require 'schemacop/validator/symbol_validator'
|
40
|
-
require 'schemacop/validator/string_validator'
|
41
|
-
require 'schemacop/validator/nil_validator'
|
42
|
-
require 'schemacop/validator/object_validator' # Matches any object, must be last validator
|
35
|
+
|
36
|
+
# Load individual versions
|
37
|
+
require 'schemacop/v2'
|
38
|
+
require 'schemacop/v3'
|
39
|
+
|
40
|
+
# Load Railtie
|
41
|
+
require 'schemacop/railtie' if defined?(Rails)
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Schemacop
|
2
|
+
class BaseSchema
|
3
|
+
attr_reader :root
|
4
|
+
|
5
|
+
# Query data validity
|
6
|
+
#
|
7
|
+
# @param data The data to validate.
|
8
|
+
# @return [Boolean] True if the data is valid, false otherwise.
|
9
|
+
def valid?(data)
|
10
|
+
validate(data).valid?
|
11
|
+
end
|
12
|
+
|
13
|
+
# Query data validity
|
14
|
+
#
|
15
|
+
# @param data The data to validate.
|
16
|
+
# @return [Boolean] True if data is invalid, false otherwise.
|
17
|
+
def invalid?(data)
|
18
|
+
!valid?(data)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Validate data for the defined Schema
|
22
|
+
#
|
23
|
+
# @param data The data to validate.
|
24
|
+
# @raise [Schemacop::Exceptions::ValidationError] If the data is invalid,
|
25
|
+
# this exception is thrown.
|
26
|
+
# @return The processed data
|
27
|
+
def validate!(data)
|
28
|
+
result = validate(data)
|
29
|
+
|
30
|
+
unless result.valid?
|
31
|
+
fail Exceptions::ValidationError, result.exception_message
|
32
|
+
end
|
33
|
+
|
34
|
+
return result.data
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/schemacop/schema.rb
CHANGED
@@ -1,62 +1,3 @@
|
|
1
1
|
module Schemacop
|
2
|
-
class Schema
|
3
|
-
# Create a new Schema
|
4
|
-
#
|
5
|
-
# For detailed usage, please refer to README.md in the root of this project.
|
6
|
-
#
|
7
|
-
# @param args [Array] An array of arguments to apply to the root node of the
|
8
|
-
# Schema.
|
9
|
-
# @param block A block with further Schema specification.
|
10
|
-
# @raise [Schemacop::Exceptions::InvalidSchemaError] If the Schema defined
|
11
|
-
# is invalid.
|
12
|
-
def initialize(*args, &block)
|
13
|
-
@root = HashValidator.new do
|
14
|
-
req :root, *args, &block
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
# Query data validity
|
19
|
-
#
|
20
|
-
# @param data The data to validate.
|
21
|
-
# @return [Boolean] True if the data is valid, false otherwise.
|
22
|
-
def valid?(data)
|
23
|
-
validate(data).valid?
|
24
|
-
end
|
25
|
-
|
26
|
-
# Query data validity
|
27
|
-
#
|
28
|
-
# @param data The data to validate.
|
29
|
-
# @return [Boolean] True if data is invalid, false otherwise.
|
30
|
-
def invalid?(data)
|
31
|
-
!valid?(data)
|
32
|
-
end
|
33
|
-
|
34
|
-
# Validate data for the defined Schema
|
35
|
-
#
|
36
|
-
# @param data The data to validate.
|
37
|
-
# @return [Schemacop::Collector] The object that collected errors
|
38
|
-
# throughout the validation.
|
39
|
-
def validate(data)
|
40
|
-
dupped_data = Schemacop::Dupper.dup_data(data)
|
41
|
-
collector = Collector.new(dupped_data)
|
42
|
-
@root.fields[:root].validate({ root: data }, collector.ignore_next_segment)
|
43
|
-
return collector
|
44
|
-
end
|
45
|
-
|
46
|
-
# Validate data for the defined Schema
|
47
|
-
#
|
48
|
-
# @param data The data to validate.
|
49
|
-
# @raise [Schemacop::Exceptions::ValidationError] If the data is invalid,
|
50
|
-
# this exception is thrown.
|
51
|
-
# @return nil
|
52
|
-
def validate!(data)
|
53
|
-
collector = validate(data)
|
54
|
-
|
55
|
-
unless collector.valid?
|
56
|
-
fail Exceptions::ValidationError, collector.exception_message
|
57
|
-
end
|
58
|
-
|
59
|
-
return collector.data
|
60
|
-
end
|
61
|
-
end
|
2
|
+
class Schema < Schemacop::Schema2; end
|
62
3
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Schemacop
|
2
|
+
class Schema2 < BaseSchema
|
3
|
+
def initialize(*args, **kwargs, &block)
|
4
|
+
super()
|
5
|
+
@root = V2::HashValidator.new do
|
6
|
+
req :root, *args, **kwargs, &block
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
# Validate data for the defined Schema
|
11
|
+
#
|
12
|
+
# @param data The data to validate.
|
13
|
+
# @return [Schemacop::Collector] The object that collected errors
|
14
|
+
# throughout the validation.
|
15
|
+
def validate(data)
|
16
|
+
dupped_data = V2::Dupper.dup_data(data)
|
17
|
+
collector = V2::Collector.new(dupped_data)
|
18
|
+
root.fields[:root].validate({ root: data }, collector.ignore_next_segment)
|
19
|
+
return collector
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Schemacop
|
2
|
+
class Schema3 < BaseSchema
|
3
|
+
def initialize(*args, **kwargs, &block)
|
4
|
+
super()
|
5
|
+
@root = V3::Node.create(*args, **kwargs, &block)
|
6
|
+
end
|
7
|
+
|
8
|
+
# Validate data for the defined Schema
|
9
|
+
#
|
10
|
+
# @param data The data to validate.
|
11
|
+
# @return [Schemacop::Collector] The object that collected errors
|
12
|
+
# throughout the validation.
|
13
|
+
def validate(data)
|
14
|
+
root.validate(data)
|
15
|
+
end
|
16
|
+
|
17
|
+
def as_json
|
18
|
+
root.as_json
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/schemacop/scoped_env.rb
CHANGED
@@ -1,18 +1,30 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
module Schemacop
|
2
|
+
class ScopedEnv
|
3
|
+
def initialize(delegation_object, methods, backup_binding = nil, prefix = nil)
|
4
|
+
@delegation_object = delegation_object
|
5
|
+
@methods = methods
|
6
|
+
@backup_binding = backup_binding
|
7
|
+
@prefix = prefix
|
8
|
+
end
|
9
|
+
|
10
|
+
def method_missing(symbol, *args, **kwargs, &block)
|
11
|
+
symbol = :"#{@prefix}#{symbol}" if @prefix
|
6
12
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
13
|
+
if @methods.include?(symbol)
|
14
|
+
if @delegation_object.respond_to?(symbol)
|
15
|
+
@delegation_object.send(symbol, *args, **kwargs, &block)
|
16
|
+
elsif @backup_binding.respond_to?(symbol)
|
17
|
+
@backup_binding.send(symbol, *args, **kwargs, &block)
|
18
|
+
else
|
19
|
+
super
|
20
|
+
end
|
21
|
+
else
|
22
|
+
super
|
23
|
+
end
|
12
24
|
end
|
13
|
-
end
|
14
25
|
|
15
|
-
|
16
|
-
|
26
|
+
def respond_to_missing?(symbol, include_private = false)
|
27
|
+
@methods.include?(symbol) || super
|
28
|
+
end
|
17
29
|
end
|
18
30
|
end
|
data/lib/schemacop/v2.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
module Schemacop::V2
|
2
|
+
module Exceptions
|
3
|
+
include Schemacop::Exceptions
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'schemacop/v2/collector'
|
8
|
+
require 'schemacop/v2/node_resolver'
|
9
|
+
require 'schemacop/v2/node'
|
10
|
+
require 'schemacop/v2/node_with_block'
|
11
|
+
require 'schemacop/v2/node_supporting_type'
|
12
|
+
require 'schemacop/v2/field_node'
|
13
|
+
require 'schemacop/v2/node_supporting_field'
|
14
|
+
require 'schemacop/v2/caster'
|
15
|
+
require 'schemacop/v2/dupper'
|
16
|
+
require 'schemacop/v2/validator/array_validator'
|
17
|
+
require 'schemacop/v2/validator/boolean_validator'
|
18
|
+
require 'schemacop/v2/validator/hash_validator'
|
19
|
+
require 'schemacop/v2/validator/number_validator'
|
20
|
+
require 'schemacop/v2/validator/integer_validator'
|
21
|
+
require 'schemacop/v2/validator/float_validator'
|
22
|
+
require 'schemacop/v2/validator/symbol_validator'
|
23
|
+
require 'schemacop/v2/validator/string_validator'
|
24
|
+
require 'schemacop/v2/validator/nil_validator'
|
25
|
+
require 'schemacop/v2/validator/object_validator' # Matches any object, must be last validator
|
@@ -1,5 +1,18 @@
|
|
1
|
-
module Schemacop
|
1
|
+
module Schemacop::V2
|
2
2
|
class Caster
|
3
|
+
DEFAULT_CASTERS = {
|
4
|
+
String => {
|
5
|
+
Integer => proc { |s| s.blank? ? nil : Integer(s, 10) },
|
6
|
+
Float => proc { |s| s.blank? ? nil : Float(s) }
|
7
|
+
},
|
8
|
+
Float => {
|
9
|
+
Integer => proc { |f| Integer(f) }
|
10
|
+
},
|
11
|
+
Integer => {
|
12
|
+
Float => proc { |f| Float(f) }
|
13
|
+
}
|
14
|
+
}.freeze
|
15
|
+
|
3
16
|
def initialize(casts, data, target_type)
|
4
17
|
@casts = casts
|
5
18
|
@data = data
|
@@ -29,8 +42,9 @@ module Schemacop
|
|
29
42
|
|
30
43
|
def cast
|
31
44
|
fail 'Not castable.' unless castable?
|
45
|
+
|
32
46
|
return @caster.call(@data)
|
33
|
-
rescue => e
|
47
|
+
rescue StandardError => e
|
34
48
|
fail Exceptions::InvalidSchemaError,
|
35
49
|
"Could not cast value #{@value.inspect} to #{@target_type}: #{e.message}."
|
36
50
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module Schemacop
|
1
|
+
module Schemacop::V2
|
2
2
|
class Collector
|
3
3
|
attr_reader :exceptions
|
4
4
|
|
@@ -12,6 +12,7 @@ module Schemacop
|
|
12
12
|
|
13
13
|
def data
|
14
14
|
return nil unless valid?
|
15
|
+
|
15
16
|
@current_datappoint_path.first
|
16
17
|
end
|
17
18
|
|
@@ -57,14 +58,16 @@ module Schemacop
|
|
57
58
|
end
|
58
59
|
|
59
60
|
def exception_message
|
61
|
+
# rubocop:disable Style/StringConcatenation
|
60
62
|
return "Schemacop validation failed:\n" + @exceptions.map do |e|
|
61
63
|
"- #{e[:path].join('')}: #{e[:message]}"
|
62
64
|
end.join("\n")
|
65
|
+
# rubocop:enable Style/StringConcatenation
|
63
66
|
end
|
64
67
|
|
65
68
|
def error(error_msg)
|
66
69
|
@exceptions << {
|
67
|
-
path:
|
70
|
+
path: @current_path.dup,
|
68
71
|
message: error_msg
|
69
72
|
}
|
70
73
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module Schemacop
|
1
|
+
module Schemacop::V2
|
2
2
|
class FieldNode < NodeSupportingType
|
3
3
|
attr_reader :name
|
4
4
|
|
@@ -14,8 +14,8 @@ module Schemacop
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def validate(data, collector)
|
17
|
-
|
18
|
-
collector.error "Missing key #{name.inspect}."
|
17
|
+
if !data.key?(name) && @required
|
18
|
+
collector.error "Missing key #{name.inspect}."
|
19
19
|
end
|
20
20
|
|
21
21
|
collector.path "/#{name}", name, :hash do
|
@@ -36,6 +36,7 @@ module Schemacop
|
|
36
36
|
|
37
37
|
@types.each do |type|
|
38
38
|
next unless type.option?(:default)
|
39
|
+
|
39
40
|
default = type.option(:default)
|
40
41
|
default = default.call if default.is_a?(Proc)
|
41
42
|
collector.override_value(default)
|
@@ -0,0 +1,142 @@
|
|
1
|
+
module Schemacop
|
2
|
+
module V2
|
3
|
+
class Node
|
4
|
+
attr_reader :options
|
5
|
+
|
6
|
+
class_attribute :allowed_options
|
7
|
+
self.allowed_options = {}.freeze
|
8
|
+
|
9
|
+
class_attribute :symbols
|
10
|
+
self.symbols = [].freeze
|
11
|
+
|
12
|
+
class_attribute :klasses
|
13
|
+
self.klasses = [].freeze
|
14
|
+
|
15
|
+
def self.option(key, default: nil)
|
16
|
+
self.allowed_options = allowed_options.merge(key => default)
|
17
|
+
end
|
18
|
+
|
19
|
+
option :if
|
20
|
+
option :check
|
21
|
+
option :cast
|
22
|
+
option :default
|
23
|
+
|
24
|
+
def type_label
|
25
|
+
str = (symbols.first || 'unknown').to_s
|
26
|
+
str += '*' if option?(:if)
|
27
|
+
return str
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.symbol(symbol)
|
31
|
+
self.symbols += [symbol]
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.clear_symbols
|
35
|
+
self.symbols = [].freeze
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.klass(klass)
|
39
|
+
self.klasses += [klass]
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.clear_klasses
|
43
|
+
self.klasses = [].freeze
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.register(symbols: [], klasses: [], clear: true, before: nil)
|
47
|
+
NodeResolver.register(self, before: before)
|
48
|
+
symbols = [*symbols]
|
49
|
+
klasses = [*klasses]
|
50
|
+
if clear
|
51
|
+
clear_symbols
|
52
|
+
clear_klasses
|
53
|
+
end
|
54
|
+
symbols.each { |s| symbol s }
|
55
|
+
klasses.each { |k| klass k }
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.type_matches?(type)
|
59
|
+
symbol_matches?(type) || class_matches?(type)
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.symbol_matches?(type)
|
63
|
+
return false unless type.is_a?(Symbol)
|
64
|
+
|
65
|
+
symbols.include?(type)
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.class_matches?(type)
|
69
|
+
return false unless type.is_a?(Class)
|
70
|
+
|
71
|
+
klasses.each do |klass|
|
72
|
+
return true if type <= klass
|
73
|
+
end
|
74
|
+
return false
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.build(options, &block)
|
78
|
+
new(options, &block)
|
79
|
+
end
|
80
|
+
|
81
|
+
def initialize(options = {})
|
82
|
+
# Check and save given options
|
83
|
+
@options = self.class.allowed_options.merge(options)
|
84
|
+
if (obsolete_opts = @options.keys - self.class.allowed_options.keys).any?
|
85
|
+
fail Exceptions::InvalidSchemaError,
|
86
|
+
"Unrecognized option(s) #{obsolete_opts.inspect} for #{self.class.inspect}, allowed options: #{self.class.allowed_options.keys.inspect}."
|
87
|
+
end
|
88
|
+
|
89
|
+
if option?(:cast) && self.class.klasses.size > 1
|
90
|
+
fail Exceptions::InvalidSchemaError,
|
91
|
+
"Casting is only allowed for single-value datatypes, but type #{self.class.inspect} has classes "\
|
92
|
+
"#{self.class.klasses.map(&:inspect)}."
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def option(key)
|
97
|
+
options[key]
|
98
|
+
end
|
99
|
+
|
100
|
+
def option?(key)
|
101
|
+
!!options[key]
|
102
|
+
end
|
103
|
+
|
104
|
+
def exec_block
|
105
|
+
fail Exceptions::InvalidSchemaError, 'Node does not support block.' if block_given?
|
106
|
+
end
|
107
|
+
|
108
|
+
def resolve_type_klass(type)
|
109
|
+
klass = NodeResolver.resolve(type)
|
110
|
+
unless klass
|
111
|
+
fail Exceptions::InvalidSchemaError, "No validation class found for type #{type.inspect}."
|
112
|
+
end
|
113
|
+
|
114
|
+
return klass
|
115
|
+
end
|
116
|
+
|
117
|
+
def validate(data, collector)
|
118
|
+
validate_custom_check(data, collector)
|
119
|
+
end
|
120
|
+
|
121
|
+
def type_matches?(data)
|
122
|
+
self.class.type_matches?(data.class) && type_filter_matches?(data)
|
123
|
+
end
|
124
|
+
|
125
|
+
def type_filter_matches?(data)
|
126
|
+
!option?(:if) || option(:if).call(data)
|
127
|
+
end
|
128
|
+
|
129
|
+
protected
|
130
|
+
|
131
|
+
def validate_custom_check(data, collector)
|
132
|
+
if option?(:check) && (check_result = option(:check).call(data)) != true
|
133
|
+
if check_result.is_a?(String)
|
134
|
+
collector.error "Custom :check failed: #{check_result}."
|
135
|
+
else
|
136
|
+
collector.error 'Custom :check failed.'
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|