dynamicschema 2.0.0 → 2.2.0
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/README.md +380 -171
- data/dynamicschema.gemspec +2 -2
- data/lib/dynamic_schema/builder.rb +12 -6
- data/lib/dynamic_schema/compiler.rb +14 -9
- data/lib/dynamic_schema/receiver/object.rb +257 -200
- data/lib/dynamic_schema/struct.rb +71 -20
- data/lib/dynamic_schema/validator.rb +39 -5
- metadata +6 -9
|
@@ -40,44 +40,69 @@ module DynamicSchema
|
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
__compiled_schema.each do | property, criteria |
|
|
43
|
-
|
|
43
|
+
|
|
44
44
|
key = ( criteria[ :as ] || property ).to_sym
|
|
45
45
|
type = criteria[ :type ]
|
|
46
46
|
default = criteria[ :default ]
|
|
47
|
+
has_multiple_types = type.is_a?( ::Array ) && criteria[ :compiler ]
|
|
47
48
|
|
|
48
|
-
if
|
|
49
|
+
if has_multiple_types
|
|
50
|
+
_criteria = criteria
|
|
51
|
+
define_method( property ) do
|
|
52
|
+
@converted_attributes.fetch( key ) do
|
|
53
|
+
value = @attributes[ key ]
|
|
54
|
+
value = default if value.nil?
|
|
55
|
+
schema = _criteria[ :schema ] ||= ( _criteria[ :compiler ]&.compiled )
|
|
56
|
+
klass = _criteria[ :class ] ||= ( schema ? ::DynamicSchema::Struct.new( schema ) : nil )
|
|
57
|
+
@converted_attributes[ key ] =
|
|
58
|
+
if _criteria[ :array ]
|
|
59
|
+
__convert_types_array( Array( value ), klass, _criteria )
|
|
60
|
+
else
|
|
61
|
+
__normalize( __convert_types( value, klass, _criteria ), _criteria )
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
elsif type == ::Object
|
|
66
|
+
_criteria = criteria
|
|
49
67
|
define_method( property ) do
|
|
50
68
|
@converted_attributes.fetch( key ) do
|
|
51
69
|
value = @attributes[ key ]
|
|
52
|
-
schema =
|
|
70
|
+
schema = _criteria[ :schema ] ||= ( _criteria[ :compiler ]&.compiled )
|
|
53
71
|
return value unless schema
|
|
54
|
-
klass =
|
|
55
|
-
@converted_attributes[ key ] =
|
|
56
|
-
if
|
|
57
|
-
Array( value || default ).map { | v | klass.build( v || {} ) }
|
|
72
|
+
klass = _criteria[ :class ] ||= ::DynamicSchema::Struct.new( schema )
|
|
73
|
+
@converted_attributes[ key ] =
|
|
74
|
+
if _criteria[ :array ]
|
|
75
|
+
Array( value || default ).map { | v | __normalize( klass.build( v || {} ), _criteria ) }
|
|
58
76
|
else
|
|
59
|
-
klass.build( value || default )
|
|
77
|
+
__normalize( klass.build( value || default ), _criteria )
|
|
60
78
|
end
|
|
61
79
|
end
|
|
62
80
|
end
|
|
63
81
|
elsif type
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
82
|
+
_criteria = criteria
|
|
83
|
+
define_method( property ) do
|
|
84
|
+
@converted_attributes.fetch( key ) do
|
|
85
|
+
value = @attributes[ key ]
|
|
86
|
+
@converted_attributes[ key ] = _criteria[ :array ] ?
|
|
87
|
+
Array( value || default ).map { | v | __normalize( __coerce( v, to: type ), _criteria ) } :
|
|
88
|
+
__normalize( __coerce( value || default, to: type ), _criteria )
|
|
70
89
|
end
|
|
71
90
|
end
|
|
72
91
|
else
|
|
92
|
+
_criteria = criteria
|
|
73
93
|
define_method( property ) do
|
|
74
|
-
@attributes[ key ] || default
|
|
75
|
-
|
|
94
|
+
value = @attributes[ key ] || default
|
|
95
|
+
if _criteria[ :array ]
|
|
96
|
+
Array( value ).map { | v | __normalize( v, _criteria ) }
|
|
97
|
+
else
|
|
98
|
+
__normalize( value, _criteria )
|
|
99
|
+
end
|
|
100
|
+
end
|
|
76
101
|
end
|
|
77
102
|
|
|
78
|
-
define_method( :"#{ property }=" ) do | value |
|
|
103
|
+
define_method( :"#{ property }=" ) do | value |
|
|
79
104
|
@converted_attributes.delete( key )
|
|
80
|
-
@attributes[ key ] = value
|
|
105
|
+
@attributes[ key ] = value
|
|
81
106
|
end
|
|
82
107
|
|
|
83
108
|
end
|
|
@@ -96,7 +121,7 @@ module DynamicSchema
|
|
|
96
121
|
result
|
|
97
122
|
end
|
|
98
123
|
|
|
99
|
-
private
|
|
124
|
+
private
|
|
100
125
|
|
|
101
126
|
def compiled_schema
|
|
102
127
|
self.class.compiled_schema
|
|
@@ -119,10 +144,36 @@ module DynamicSchema
|
|
|
119
144
|
end
|
|
120
145
|
end
|
|
121
146
|
|
|
122
|
-
def
|
|
147
|
+
def __coerce( value, to: )
|
|
123
148
|
self.class.converter.convert( value, to: to ) { | v | to.new( v ) rescue nil }
|
|
124
149
|
end
|
|
125
150
|
|
|
151
|
+
def __convert_types( value, klass, criteria )
|
|
152
|
+
return nil if value.nil?
|
|
153
|
+
if value.is_a?( ::Hash )
|
|
154
|
+
klass ? klass.build( value ) : value
|
|
155
|
+
else
|
|
156
|
+
scalar_types = __non_object_types( criteria[ :type ] )
|
|
157
|
+
__coerce( value, to: scalar_types )
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def __convert_types_array( values, klass, criteria )
|
|
162
|
+
values.map { | v | __normalize( __convert_types( v, klass, criteria ), criteria ) }
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def __non_object_types( types )
|
|
166
|
+
types_array = types.is_a?( ::Array ) ? types : [ types ]
|
|
167
|
+
result = types_array.reject { | type | type == ::Object }
|
|
168
|
+
result.length == 1 ? result.first : result
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def __normalize( value, criteria )
|
|
172
|
+
normalize = criteria[ :normalize ]
|
|
173
|
+
return value unless normalize && !value.nil?
|
|
174
|
+
normalize.call( value )
|
|
175
|
+
end
|
|
176
|
+
|
|
126
177
|
end
|
|
127
178
|
__klass.instance_variable_set( :@__compiled_schema, __compiled_schema.dup )
|
|
128
179
|
__klass.instance_variable_set( :@__converter, __converter )
|
|
@@ -40,6 +40,33 @@ module DynamicSchema
|
|
|
40
40
|
type_match
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
+
def __validate_types( value, criteria, path, key, &block )
|
|
44
|
+
if value.is_a?( ::Hash )
|
|
45
|
+
traverse_and_validate_values(
|
|
46
|
+
value,
|
|
47
|
+
schema: criteria[ :schema ] ||= criteria[ :compiler ].compiled,
|
|
48
|
+
path: "#{ ( path || '' ) + ( path ? '/' : '' ) + key.to_s }",
|
|
49
|
+
&block
|
|
50
|
+
)
|
|
51
|
+
else
|
|
52
|
+
scalar_types = __non_object_types( criteria[ :type ] )
|
|
53
|
+
unless value_matches_types?( value, scalar_types )
|
|
54
|
+
block.call( IncompatibleTypeError.new( path: path, key: key, type: criteria[ :type ], value: value ) )
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def __validate_types_array( values, criteria, path, key, &block )
|
|
60
|
+
values.each do | value |
|
|
61
|
+
__validate_types( value, criteria, path, key, &block )
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def __non_object_types( types )
|
|
66
|
+
types_array = types.is_a?( ::Array ) ? types : [ types ]
|
|
67
|
+
types_array.reject { | type | type == ::Object }
|
|
68
|
+
end
|
|
69
|
+
|
|
43
70
|
def traverse_and_validate_values( values, schema:, path: nil, options: nil, &block )
|
|
44
71
|
path.chomp( '/' ) if path
|
|
45
72
|
unless values.respond_to?( :[] )
|
|
@@ -59,8 +86,13 @@ module DynamicSchema
|
|
|
59
86
|
end
|
|
60
87
|
end
|
|
61
88
|
elsif !criteria[ :default_assigned ] && !value.nil?
|
|
89
|
+
type = criteria[ :type ]
|
|
90
|
+
has_multiple_types = type.is_a?( ::Array ) && criteria[ :compiler ]
|
|
91
|
+
|
|
62
92
|
unless criteria[ :array ]
|
|
63
|
-
if
|
|
93
|
+
if has_multiple_types
|
|
94
|
+
__validate_types( value, criteria, path, key, &block )
|
|
95
|
+
elsif type == Object
|
|
64
96
|
traverse_and_validate_values(
|
|
65
97
|
values[ name ],
|
|
66
98
|
schema: criteria[ :schema ] ||= criteria[ :compiler ].compiled,
|
|
@@ -68,14 +100,16 @@ module DynamicSchema
|
|
|
68
100
|
&block
|
|
69
101
|
)
|
|
70
102
|
else
|
|
71
|
-
if
|
|
72
|
-
unless value_matches_types?( value,
|
|
73
|
-
block.call( IncompatibleTypeError.new( path: path, key: key, type:
|
|
103
|
+
if type && value && !criteria[ :default_assigned ]
|
|
104
|
+
unless value_matches_types?( value, type )
|
|
105
|
+
block.call( IncompatibleTypeError.new( path: path, key: key, type: type, value: value ) )
|
|
74
106
|
end
|
|
75
107
|
end
|
|
76
108
|
end
|
|
77
109
|
else
|
|
78
|
-
if
|
|
110
|
+
if has_multiple_types
|
|
111
|
+
__validate_types_array( Array( value ), criteria, path, key, &block )
|
|
112
|
+
elsif type == Object
|
|
79
113
|
groups = Array( value )
|
|
80
114
|
groups.each do | group |
|
|
81
115
|
traverse_and_validate_values(
|
metadata
CHANGED
|
@@ -1,29 +1,28 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dynamicschema
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kristoph Cichocki-Romanov
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
|
-
name:
|
|
13
|
+
name: minitest
|
|
15
14
|
requirement: !ruby/object:Gem::Requirement
|
|
16
15
|
requirements:
|
|
17
16
|
- - "~>"
|
|
18
17
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '
|
|
18
|
+
version: '6.0'
|
|
20
19
|
type: :development
|
|
21
20
|
prerelease: false
|
|
22
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
22
|
requirements:
|
|
24
23
|
- - "~>"
|
|
25
24
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '
|
|
25
|
+
version: '6.0'
|
|
27
26
|
- !ruby/object:Gem::Dependency
|
|
28
27
|
name: debug
|
|
29
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -76,7 +75,6 @@ licenses:
|
|
|
76
75
|
metadata:
|
|
77
76
|
source_code_uri: https://github.com/EndlessInternational/dynamic_schema
|
|
78
77
|
bug_tracker_uri: https://github.com/EndlessInternational/dynamic_schema/issues
|
|
79
|
-
post_install_message:
|
|
80
78
|
rdoc_options: []
|
|
81
79
|
require_paths:
|
|
82
80
|
- lib
|
|
@@ -91,8 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
91
89
|
- !ruby/object:Gem::Version
|
|
92
90
|
version: '0'
|
|
93
91
|
requirements: []
|
|
94
|
-
rubygems_version: 3.
|
|
95
|
-
signing_key:
|
|
92
|
+
rubygems_version: 3.6.7
|
|
96
93
|
specification_version: 4
|
|
97
94
|
summary: DynamicSchema is a lightweight and simple yet powerful gem that enables flexible
|
|
98
95
|
semantic schema definitions for constructing and validating complex configurations
|