@@ -60,7 +60,7 @@ def fields
60
60
[ OnebusawaySDK ::Internal ::Type ::Converter . type_info ( type_info ) , type_info ]
61
61
end
62
62
63
- setter = "#{ name_sym } ="
63
+ setter = : "#{ name_sym } ="
64
64
api_name = info . fetch ( :api_name , name_sym )
65
65
nilable = info . fetch ( :nil? , false )
66
66
const = if required && !nilable
@@ -84,28 +84,61 @@ def fields
84
84
type_fn : type_fn
85
85
}
86
86
87
- define_method ( setter ) { @data . store ( name_sym , _1 ) }
87
+ define_method ( setter ) do |value |
88
+ target = type_fn . call
89
+ state = OnebusawaySDK ::Internal ::Type ::Converter . new_coerce_state ( translate_names : false )
90
+ coerced = OnebusawaySDK ::Internal ::Type ::Converter . coerce ( target , value , state : state )
91
+ status = @coerced . store ( name_sym , state . fetch ( :error ) || true )
92
+ stored =
93
+ case [ target , status ]
94
+ in [ OnebusawaySDK ::Internal ::Type ::Converter | Symbol , true ]
95
+ coerced
96
+ else
97
+ value
98
+ end
99
+ @data . store ( name_sym , stored )
100
+ end
88
101
102
+ # rubocop:disable Style/CaseEquality
103
+ # rubocop:disable Metrics/BlockLength
89
104
define_method ( name_sym ) do
90
105
target = type_fn . call
91
- value = @data . fetch ( name_sym ) { const == OnebusawaySDK ::Internal ::OMIT ? nil : const }
92
- state = { strictness : :strong , exactness : { yes : 0 , no : 0 , maybe : 0 } , branched : 0 }
93
- if ( nilable || !required ) && value . nil?
94
- nil
95
- else
96
- OnebusawaySDK ::Internal ::Type ::Converter . coerce (
97
- target , value , state : state
106
+
107
+ case @coerced [ name_sym ]
108
+ in true | false if OnebusawaySDK ::Internal ::Type ::Converter === target
109
+ @data . fetch ( name_sym )
110
+ in ::StandardError => e
111
+ raise OnebusawaySDK ::Errors ::ConversionError . new (
112
+ on : self . class ,
113
+ method : __method__ ,
114
+ target : target ,
115
+ value : @data . fetch ( name_sym ) ,
116
+ cause : e
98
117
)
118
+ else
119
+ Kernel . then do
120
+ value = @data . fetch ( name_sym ) { const == OnebusawaySDK ::Internal ::OMIT ? nil : const }
121
+ state = OnebusawaySDK ::Internal ::Type ::Converter . new_coerce_state ( translate_names : false )
122
+ if ( nilable || !required ) && value . nil?
123
+ nil
124
+ else
125
+ OnebusawaySDK ::Internal ::Type ::Converter . coerce (
126
+ target , value , state : state
127
+ )
128
+ end
129
+ rescue StandardError => e
130
+ raise OnebusawaySDK ::Errors ::ConversionError . new (
131
+ on : self . class ,
132
+ method : __method__ ,
133
+ target : target ,
134
+ value : value ,
135
+ cause : e
136
+ )
137
+ end
99
138
end
100
- rescue StandardError => e
101
- cls = self . class . name . split ( "::" ) . last
102
- message = [
103
- "Failed to parse #{ cls } .#{ __method__ } from #{ value . class } to #{ target . inspect } ." ,
104
- "To get the unparsed API response, use #{ cls } [#{ __method__ . inspect } ]." ,
105
- "Cause: #{ e . message } "
106
- ] . join ( " " )
107
- raise OnebusawaySDK ::Errors ::ConversionError . new ( message )
108
139
end
140
+ # rubocop:enable Metrics/BlockLength
141
+ # rubocop:enable Style/CaseEquality
109
142
end
110
143
111
144
# @api private
@@ -205,37 +238,44 @@ class << self
205
238
#
206
239
# @param state [Hash{Symbol=>Object}] .
207
240
#
208
- # @option state [Boolean, :strong] :strictness
241
+ # @option state [Boolean] :translate_names
242
+ #
243
+ # @option state [Boolean] :strictness
209
244
#
210
245
# @option state [Hash{Symbol=>Object}] :exactness
211
246
#
247
+ # @option state [Class<StandardError>] :error
248
+ #
212
249
# @option state [Integer] :branched
213
250
#
214
251
# @return [self, Object]
215
252
def coerce ( value , state :)
216
253
exactness = state . fetch ( :exactness )
217
254
218
- if value . is_a? ( self . class )
255
+ if value . is_a? ( self )
219
256
exactness [ :yes ] += 1
220
257
return value
221
258
end
222
259
223
260
unless ( val = OnebusawaySDK ::Internal ::Util . coerce_hash ( value ) ) . is_a? ( Hash )
224
261
exactness [ :no ] += 1
262
+ state [ :error ] = TypeError . new ( "#{ value . class } can't be coerced into #{ Hash } " )
225
263
return value
226
264
end
227
265
exactness [ :yes ] += 1
228
266
229
267
keys = val . keys . to_set
230
268
instance = new
231
269
data = instance . to_h
270
+ status = instance . instance_variable_get ( :@coerced )
232
271
233
272
# rubocop:disable Metrics/BlockLength
234
273
fields . each do |name , field |
235
274
mode , required , target = field . fetch_values ( :mode , :required , :type )
236
275
api_name , nilable , const = field . fetch_values ( :api_name , :nilable , :const )
276
+ src_name = state . fetch ( :translate_names ) ? api_name : name
237
277
238
- unless val . key? ( api_name )
278
+ unless val . key? ( src_name )
239
279
if required && mode != :dump && const == OnebusawaySDK ::Internal ::OMIT
240
280
exactness [ nilable ? :maybe : :no ] += 1
241
281
else
@@ -244,9 +284,10 @@ def coerce(value, state:)
244
284
next
245
285
end
246
286
247
- item = val . fetch ( api_name )
248
- keys . delete ( api_name )
287
+ item = val . fetch ( src_name )
288
+ keys . delete ( src_name )
249
289
290
+ state [ :error ] = nil
250
291
converted =
251
292
if item . nil? && ( nilable || !required )
252
293
exactness [ nilable ? :yes : :maybe ] += 1
@@ -260,6 +301,8 @@ def coerce(value, state:)
260
301
item
261
302
end
262
303
end
304
+
305
+ status . store ( name , state . fetch ( :error ) || true )
263
306
data . store ( name , converted )
264
307
end
265
308
# rubocop:enable Metrics/BlockLength
@@ -438,7 +481,18 @@ def to_yaml(*a) = OnebusawaySDK::Internal::Type::Converter.dump(self.class, self
438
481
# Create a new instance of a model.
439
482
#
440
483
# @param data [Hash{Symbol=>Object}, self]
441
- def initialize ( data = { } ) = ( @data = OnebusawaySDK ::Internal ::Util . coerce_hash! ( data ) . to_h )
484
+ def initialize ( data = { } )
485
+ @data = { }
486
+ @coerced = { }
487
+ OnebusawaySDK ::Internal ::Util . coerce_hash! ( data ) . each do
488
+ if self . class . known_fields . key? ( _1 )
489
+ public_send ( :"#{ _1 } =" , _2 )
490
+ else
491
+ @data . store ( _1 , _2 )
492
+ @coerced . store ( _1 , false )
493
+ end
494
+ end
495
+ end
442
496
443
497
class << self
444
498
# @api private
0 commit comments