schemacop 2.4.6 → 3.0.0.rc3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|