dynamicschema 2.0.0 → 2.1.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.
@@ -40,19 +40,35 @@ 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 type == ::Object
49
+ if has_multiple_types
50
+ define_method( property ) do
51
+ @converted_attributes.fetch( key ) do
52
+ value = @attributes[ key ]
53
+ value = default if value.nil?
54
+ schema = criteria[ :schema ] ||= ( criteria[ :compiler ]&.compiled )
55
+ klass = criteria[ :class ] ||= ( schema ? ::DynamicSchema::Struct.new( schema ) : nil )
56
+ @converted_attributes[ key ] =
57
+ if criteria[ :array ]
58
+ __convert_types_array( Array( value ), klass, criteria )
59
+ else
60
+ __convert_types( value, klass, criteria )
61
+ end
62
+ end
63
+ end
64
+ elsif type == ::Object
49
65
  define_method( property ) do
50
66
  @converted_attributes.fetch( key ) do
51
67
  value = @attributes[ key ]
52
68
  schema = criteria[ :schema ] ||= ( criteria[ :compiler ]&.compiled )
53
69
  return value unless schema
54
70
  klass = criteria[ :class ] ||= ::DynamicSchema::Struct.new( schema )
55
- @converted_attributes[ key ] =
71
+ @converted_attributes[ key ] =
56
72
  if criteria[ :array ]
57
73
  Array( value || default ).map { | v | klass.build( v || {} ) }
58
74
  else
@@ -61,23 +77,23 @@ module DynamicSchema
61
77
  end
62
78
  end
63
79
  elsif type
64
- define_method( property ) do
65
- @converted_attributes.fetch( key ) do
66
- value = @attributes[ key ]
67
- @converted_attributes[ key ] = criteria[ :array ] ?
68
- Array( value || default ).map { | v | __convert( v, to: type ) } :
80
+ define_method( property ) do
81
+ @converted_attributes.fetch( key ) do
82
+ value = @attributes[ key ]
83
+ @converted_attributes[ key ] = criteria[ :array ] ?
84
+ Array( value || default ).map { | v | __convert( v, to: type ) } :
69
85
  __convert( value || default, to: type )
70
86
  end
71
87
  end
72
88
  else
73
89
  define_method( property ) do
74
90
  @attributes[ key ] || default
75
- end
91
+ end
76
92
  end
77
93
 
78
- define_method( :"#{ property }=" ) do | value |
94
+ define_method( :"#{ property }=" ) do | value |
79
95
  @converted_attributes.delete( key )
80
- @attributes[ key ] = value
96
+ @attributes[ key ] = value
81
97
  end
82
98
 
83
99
  end
@@ -96,7 +112,7 @@ module DynamicSchema
96
112
  result
97
113
  end
98
114
 
99
- private
115
+ private
100
116
 
101
117
  def compiled_schema
102
118
  self.class.compiled_schema
@@ -123,6 +139,26 @@ module DynamicSchema
123
139
  self.class.converter.convert( value, to: to ) { | v | to.new( v ) rescue nil }
124
140
  end
125
141
 
142
+ def __convert_types( value, klass, criteria )
143
+ return nil if value.nil?
144
+ if value.is_a?( ::Hash )
145
+ klass ? klass.build( value ) : value
146
+ else
147
+ scalar_types = __non_object_types( criteria[ :type ] )
148
+ __convert( value, to: scalar_types )
149
+ end
150
+ end
151
+
152
+ def __convert_types_array( values, klass, criteria )
153
+ values.map { | v | __convert_types( v, klass, criteria ) }
154
+ end
155
+
156
+ def __non_object_types( types )
157
+ types_array = types.is_a?( ::Array ) ? types : [ types ]
158
+ result = types_array.reject { | type | type == ::Object }
159
+ result.length == 1 ? result.first : result
160
+ end
161
+
126
162
  end
127
163
  __klass.instance_variable_set( :@__compiled_schema, __compiled_schema.dup )
128
164
  __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 criteria[ :type ] == Object
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 criteria[ :type ] && value && !criteria[ :default_assigned ]
72
- unless value_matches_types?( value, criteria[ :type ] )
73
- block.call( IncompatibleTypeError.new( path: path, key: key, type: criteria[ :type ], value: value ) )
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 criteria[ :type ] == Object
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.0.0
4
+ version: 2.1.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: 2025-09-06 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
- name: rspec
13
+ name: minitest
15
14
  requirement: !ruby/object:Gem::Requirement
16
15
  requirements:
17
16
  - - "~>"
18
17
  - !ruby/object:Gem::Version
19
- version: '3.13'
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: '3.13'
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.5.22
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