crisphive 0.2.0 → 0.3.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.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +98 -10
  3. data/lib/crisphive/api/business_skill_api.rb +348 -0
  4. data/lib/crisphive/api/customer_api.rb +7 -4
  5. data/lib/crisphive/api/job_request_business_api.rb +243 -27
  6. data/lib/crisphive/api/job_types_api.rb +208 -0
  7. data/lib/crisphive/api/permission_api.rb +79 -0
  8. data/lib/crisphive/api/service_area_api.rb +208 -0
  9. data/lib/crisphive/api/technician_api.rb +8 -8
  10. data/lib/crisphive/api/technician_time_off_api.rb +240 -0
  11. data/lib/crisphive/api/vehicle_api.rb +208 -0
  12. data/lib/crisphive/api/webhooks_api.rb +213 -0
  13. data/lib/crisphive/models/api_internal_techtimeoff_actions.rb +232 -0
  14. data/lib/crisphive/models/api_internal_techtimeoff_status.rb +42 -0
  15. data/lib/crisphive/models/assignable_group.rb +289 -0
  16. data/lib/crisphive/models/book_and_confirm_job_request200_response.rb +253 -0
  17. data/lib/crisphive/models/commit_absence_resolve200_response.rb +253 -0
  18. data/lib/crisphive/models/create_job_type200_response.rb +253 -0
  19. data/lib/crisphive/models/create_service_area200_response.rb +253 -0
  20. data/lib/crisphive/models/create_skill200_response.rb +253 -0
  21. data/lib/crisphive/models/create_skill_category200_response.rb +253 -0
  22. data/lib/crisphive/models/create_technician_time_off200_response.rb +253 -0
  23. data/lib/crisphive/models/create_vehicle200_response.rb +253 -0
  24. data/lib/crisphive/models/create_webhook_endpoint200_response.rb +253 -0
  25. data/lib/crisphive/models/customer.rb +11 -1
  26. data/lib/crisphive/models/customer_contact.rb +25 -5
  27. data/lib/crisphive/models/customer_create_request.rb +12 -2
  28. data/lib/crisphive/models/customer_list_item.rb +11 -1
  29. data/lib/crisphive/models/customer_quick_books_link.rb +235 -0
  30. data/lib/crisphive/models/customer_service_area_ref.rb +225 -0
  31. data/lib/crisphive/models/customer_technician_ref.rb +225 -0
  32. data/lib/crisphive/models/customer_update_request.rb +23 -20
  33. data/lib/crisphive/models/internal_jobrequest_http_address_req.rb +475 -0
  34. data/lib/crisphive/models/job_request.rb +11 -1
  35. data/lib/crisphive/models/job_request_absence_alternative.rb +356 -0
  36. data/lib/crisphive/models/job_request_absence_alternative_cost.rb +275 -0
  37. data/lib/crisphive/models/job_request_absence_assignment.rb +319 -0
  38. data/lib/crisphive/models/job_request_absence_commit_request.rb +296 -0
  39. data/lib/crisphive/models/job_request_absence_notification.rb +283 -0
  40. data/lib/crisphive/models/job_request_absence_plan.rb +322 -0
  41. data/lib/crisphive/models/job_request_absence_preview_request.rb +280 -0
  42. data/lib/crisphive/models/job_request_absence_resolved_job.rb +499 -0
  43. data/lib/crisphive/models/job_request_absence_solver.rb +289 -0
  44. data/lib/crisphive/models/job_request_absence_time_off.rb +281 -0
  45. data/lib/crisphive/models/job_request_absence_unresolved_job.rb +364 -0
  46. data/lib/crisphive/models/job_request_action_summary.rb +1 -1
  47. data/lib/crisphive/models/job_request_attention_summary.rb +2 -2
  48. data/lib/crisphive/models/job_request_blocker.rb +363 -0
  49. data/lib/crisphive/models/job_request_blocker_ref.rb +223 -0
  50. data/lib/crisphive/models/job_request_book_and_confirm_customer.rb +302 -0
  51. data/lib/crisphive/models/job_request_book_and_confirm_emergency.rb +315 -0
  52. data/lib/crisphive/models/job_request_book_and_confirm_emergency_result.rb +279 -0
  53. data/lib/crisphive/models/job_request_book_and_confirm_refusal.rb +280 -0
  54. data/lib/crisphive/models/job_request_book_and_confirm_request.rb +466 -0
  55. data/lib/crisphive/models/job_request_book_and_confirm_response.rb +295 -0
  56. data/lib/crisphive/models/job_request_confirm_request.rb +14 -4
  57. data/lib/crisphive/models/job_request_create_request.rb +1 -1
  58. data/lib/crisphive/models/job_request_emergency_candidate.rb +26 -4
  59. data/lib/crisphive/models/job_request_emergency_candidates.rb +1 -1
  60. data/lib/crisphive/models/job_request_emergency_candidates_request.rb +24 -11
  61. data/lib/crisphive/models/job_request_emergency_commit_request.rb +11 -1
  62. data/lib/crisphive/models/job_request_emergency_inline_job.rb +353 -0
  63. data/lib/crisphive/models/job_request_emergency_plan.rb +25 -3
  64. data/lib/crisphive/models/job_request_emergency_preview_request.rb +24 -11
  65. data/lib/crisphive/models/job_request_move_commit_req.rb +11 -1
  66. data/lib/crisphive/models/job_request_move_plan.rb +11 -1
  67. data/lib/crisphive/models/job_request_move_preview_req.rb +11 -1
  68. data/lib/crisphive/models/job_request_move_warning.rb +32 -8
  69. data/lib/crisphive/models/job_request_priority_update_result.rb +217 -0
  70. data/lib/crisphive/models/job_request_quote_request.rb +14 -11
  71. data/lib/crisphive/models/job_request_reassign_fallback.rb +287 -0
  72. data/lib/crisphive/models/job_request_skill_summary.rb +1 -1
  73. data/lib/crisphive/models/job_request_status_summary.rb +1 -1
  74. data/lib/crisphive/models/job_request_time_segments.rb +2 -2
  75. data/lib/crisphive/models/job_type.rb +42 -2
  76. data/lib/crisphive/models/job_type_create_request.rb +399 -0
  77. data/lib/crisphive/models/job_type_create_response.rb +215 -0
  78. data/lib/crisphive/models/job_type_update_request.rb +400 -0
  79. data/lib/crisphive/models/list_assignable_groups200_response.rb +255 -0
  80. data/lib/crisphive/models/list_technician_time_off200_response.rb +253 -0
  81. data/lib/crisphive/models/list_webhook_event_types200_response.rb +255 -0
  82. data/lib/crisphive/models/quote_job_request200_response.rb +253 -0
  83. data/lib/crisphive/models/service_area.rb +21 -1
  84. data/lib/crisphive/models/service_area_create_request.rb +455 -0
  85. data/lib/crisphive/models/service_area_create_response.rb +215 -0
  86. data/lib/crisphive/models/service_area_update_request.rb +451 -0
  87. data/lib/crisphive/models/skill_category_create_request.rb +270 -0
  88. data/lib/crisphive/models/skill_category_create_response.rb +215 -0
  89. data/lib/crisphive/models/skill_create_request.rb +270 -0
  90. data/lib/crisphive/models/skill_create_response.rb +215 -0
  91. data/lib/crisphive/models/skill_update_request.rb +281 -0
  92. data/lib/crisphive/models/technician.rb +64 -2
  93. data/lib/crisphive/models/technician_create_request.rb +14 -11
  94. data/lib/crisphive/models/technician_time_off.rb +334 -0
  95. data/lib/crisphive/models/technician_time_off_create_request.rb +285 -0
  96. data/lib/crisphive/models/technician_time_off_create_response.rb +215 -0
  97. data/lib/crisphive/models/technician_time_off_list.rb +246 -0
  98. data/lib/crisphive/models/technician_update_request.rb +2 -2
  99. data/lib/crisphive/models/vehicle_create_request.rb +420 -0
  100. data/lib/crisphive/models/vehicle_create_response.rb +215 -0
  101. data/lib/crisphive/models/vehicle_update_request.rb +440 -0
  102. data/lib/crisphive/models/webhook_create_request.rb +320 -0
  103. data/lib/crisphive/models/webhook_create_response.rb +391 -0
  104. data/lib/crisphive/models/webhook_verification.rb +235 -0
  105. data/lib/crisphive/version.rb +1 -1
  106. data/lib/crisphive.rb +66 -0
  107. metadata +68 -2
@@ -0,0 +1,451 @@
1
+ =begin
2
+ #Crisphive Developer API
3
+
4
+ #Public REST API for integrating Crisphive from your own backend. Authenticate every request with a secret API key as a Bearer token (`Authorization: Bearer chsk_live_…`). The key prefix selects the data environment: `chsk_live_…` → production (live), `chsk_test_…` → sandbox (isolated test). **Key scopes (restricted keys).** A key is either *full-access* (can call every endpoint below) or *restricted* to a set of permission codes chosen at creation — the same codes as the dashboard permission grid (e.g. `customers_view`, `job_create`, `team_manage`). A restricted key calling an endpoint outside its scope gets `403`. The full code list is the permission catalog (`GET /permission/modules` on the dashboard API). Create, scope, and revoke keys from the business dashboard. Every response is wrapped in the envelope `{ \"error_code\": 0, \"message\": \"Success\", \"data\": <payload> }`.
5
+
6
+ The version of the OpenAPI document: 1.0
7
+
8
+ Generated by: https://openapi-generator.tech
9
+ Generator version: 7.11.0
10
+
11
+ =end
12
+
13
+ require 'date'
14
+ require 'time'
15
+
16
+ module Crisphive
17
+ # Service area update request
18
+ class ServiceAreaUpdateRequest
19
+ # GeoJSON polygon boundary. Omit to KEEP the stored polygon; send one to replace it.
20
+ attr_accessor :boundary
21
+
22
+ attr_accessor :city
23
+
24
+ attr_accessor :country
25
+
26
+ attr_accessor :county
27
+
28
+ # nil = keep; \"\" clears it.
29
+ attr_accessor :description
30
+
31
+ attr_accessor :district
32
+
33
+ # nil = keep; min=1 rejects an explicit \"\".
34
+ attr_accessor :name
35
+
36
+ attr_accessor :postal_code
37
+
38
+ attr_accessor :state_province
39
+
40
+ # Attribute mapping from ruby-style variable name to JSON key.
41
+ def self.attribute_map
42
+ {
43
+ :'boundary' => :'boundary',
44
+ :'city' => :'city',
45
+ :'country' => :'country',
46
+ :'county' => :'county',
47
+ :'description' => :'description',
48
+ :'district' => :'district',
49
+ :'name' => :'name',
50
+ :'postal_code' => :'postal_code',
51
+ :'state_province' => :'state_province'
52
+ }
53
+ end
54
+
55
+ # Returns all the JSON keys this model knows about
56
+ def self.acceptable_attributes
57
+ attribute_map.values
58
+ end
59
+
60
+ # Attribute type mapping.
61
+ def self.openapi_types
62
+ {
63
+ :'boundary' => :'Object',
64
+ :'city' => :'String',
65
+ :'country' => :'String',
66
+ :'county' => :'String',
67
+ :'description' => :'String',
68
+ :'district' => :'String',
69
+ :'name' => :'String',
70
+ :'postal_code' => :'String',
71
+ :'state_province' => :'String'
72
+ }
73
+ end
74
+
75
+ # List of attributes with nullable: true
76
+ def self.openapi_nullable
77
+ Set.new([
78
+ ])
79
+ end
80
+
81
+ # Initializes the object
82
+ # @param [Hash] attributes Model attributes in the form of hash
83
+ def initialize(attributes = {})
84
+ if (!attributes.is_a?(Hash))
85
+ fail ArgumentError, "The input argument (attributes) must be a hash in `Crisphive::ServiceAreaUpdateRequest` initialize method"
86
+ end
87
+
88
+ # check to see if the attribute exists and convert string to symbol for hash key
89
+ attributes = attributes.each_with_object({}) { |(k, v), h|
90
+ if (!self.class.attribute_map.key?(k.to_sym))
91
+ fail ArgumentError, "`#{k}` is not a valid attribute in `Crisphive::ServiceAreaUpdateRequest`. Please check the name to make sure it's valid. List of attributes: " + self.class.attribute_map.keys.inspect
92
+ end
93
+ h[k.to_sym] = v
94
+ }
95
+
96
+ if attributes.key?(:'boundary')
97
+ self.boundary = attributes[:'boundary']
98
+ end
99
+
100
+ if attributes.key?(:'city')
101
+ self.city = attributes[:'city']
102
+ end
103
+
104
+ if attributes.key?(:'country')
105
+ self.country = attributes[:'country']
106
+ end
107
+
108
+ if attributes.key?(:'county')
109
+ self.county = attributes[:'county']
110
+ end
111
+
112
+ if attributes.key?(:'description')
113
+ self.description = attributes[:'description']
114
+ end
115
+
116
+ if attributes.key?(:'district')
117
+ self.district = attributes[:'district']
118
+ end
119
+
120
+ if attributes.key?(:'name')
121
+ self.name = attributes[:'name']
122
+ end
123
+
124
+ if attributes.key?(:'postal_code')
125
+ self.postal_code = attributes[:'postal_code']
126
+ end
127
+
128
+ if attributes.key?(:'state_province')
129
+ self.state_province = attributes[:'state_province']
130
+ end
131
+ end
132
+
133
+ # Show invalid properties with the reasons. Usually used together with valid?
134
+ # @return Array for valid properties with the reasons
135
+ def list_invalid_properties
136
+ warn '[DEPRECATED] the `list_invalid_properties` method is obsolete'
137
+ invalid_properties = Array.new
138
+ if !@city.nil? && @city.to_s.length > 100
139
+ invalid_properties.push('invalid value for "city", the character length must be smaller than or equal to 100.')
140
+ end
141
+
142
+ if !@country.nil? && @country.to_s.length > 100
143
+ invalid_properties.push('invalid value for "country", the character length must be smaller than or equal to 100.')
144
+ end
145
+
146
+ if !@county.nil? && @county.to_s.length > 100
147
+ invalid_properties.push('invalid value for "county", the character length must be smaller than or equal to 100.')
148
+ end
149
+
150
+ if !@description.nil? && @description.to_s.length > 1000
151
+ invalid_properties.push('invalid value for "description", the character length must be smaller than or equal to 1000.')
152
+ end
153
+
154
+ if !@district.nil? && @district.to_s.length > 100
155
+ invalid_properties.push('invalid value for "district", the character length must be smaller than or equal to 100.')
156
+ end
157
+
158
+ if !@name.nil? && @name.to_s.length > 255
159
+ invalid_properties.push('invalid value for "name", the character length must be smaller than or equal to 255.')
160
+ end
161
+
162
+ if !@name.nil? && @name.to_s.length < 1
163
+ invalid_properties.push('invalid value for "name", the character length must be great than or equal to 1.')
164
+ end
165
+
166
+ if !@postal_code.nil? && @postal_code.to_s.length > 20
167
+ invalid_properties.push('invalid value for "postal_code", the character length must be smaller than or equal to 20.')
168
+ end
169
+
170
+ if !@state_province.nil? && @state_province.to_s.length > 100
171
+ invalid_properties.push('invalid value for "state_province", the character length must be smaller than or equal to 100.')
172
+ end
173
+
174
+ invalid_properties
175
+ end
176
+
177
+ # Check to see if the all the properties in the model are valid
178
+ # @return true if the model is valid
179
+ def valid?
180
+ warn '[DEPRECATED] the `valid?` method is obsolete'
181
+ return false if !@city.nil? && @city.to_s.length > 100
182
+ return false if !@country.nil? && @country.to_s.length > 100
183
+ return false if !@county.nil? && @county.to_s.length > 100
184
+ return false if !@description.nil? && @description.to_s.length > 1000
185
+ return false if !@district.nil? && @district.to_s.length > 100
186
+ return false if !@name.nil? && @name.to_s.length > 255
187
+ return false if !@name.nil? && @name.to_s.length < 1
188
+ return false if !@postal_code.nil? && @postal_code.to_s.length > 20
189
+ return false if !@state_province.nil? && @state_province.to_s.length > 100
190
+ true
191
+ end
192
+
193
+ # Custom attribute writer method with validation
194
+ # @param [Object] city Value to be assigned
195
+ def city=(city)
196
+ if city.nil?
197
+ fail ArgumentError, 'city cannot be nil'
198
+ end
199
+
200
+ if city.to_s.length > 100
201
+ fail ArgumentError, 'invalid value for "city", the character length must be smaller than or equal to 100.'
202
+ end
203
+
204
+ @city = city
205
+ end
206
+
207
+ # Custom attribute writer method with validation
208
+ # @param [Object] country Value to be assigned
209
+ def country=(country)
210
+ if country.nil?
211
+ fail ArgumentError, 'country cannot be nil'
212
+ end
213
+
214
+ if country.to_s.length > 100
215
+ fail ArgumentError, 'invalid value for "country", the character length must be smaller than or equal to 100.'
216
+ end
217
+
218
+ @country = country
219
+ end
220
+
221
+ # Custom attribute writer method with validation
222
+ # @param [Object] county Value to be assigned
223
+ def county=(county)
224
+ if county.nil?
225
+ fail ArgumentError, 'county cannot be nil'
226
+ end
227
+
228
+ if county.to_s.length > 100
229
+ fail ArgumentError, 'invalid value for "county", the character length must be smaller than or equal to 100.'
230
+ end
231
+
232
+ @county = county
233
+ end
234
+
235
+ # Custom attribute writer method with validation
236
+ # @param [Object] description Value to be assigned
237
+ def description=(description)
238
+ if description.nil?
239
+ fail ArgumentError, 'description cannot be nil'
240
+ end
241
+
242
+ if description.to_s.length > 1000
243
+ fail ArgumentError, 'invalid value for "description", the character length must be smaller than or equal to 1000.'
244
+ end
245
+
246
+ @description = description
247
+ end
248
+
249
+ # Custom attribute writer method with validation
250
+ # @param [Object] district Value to be assigned
251
+ def district=(district)
252
+ if district.nil?
253
+ fail ArgumentError, 'district cannot be nil'
254
+ end
255
+
256
+ if district.to_s.length > 100
257
+ fail ArgumentError, 'invalid value for "district", the character length must be smaller than or equal to 100.'
258
+ end
259
+
260
+ @district = district
261
+ end
262
+
263
+ # Custom attribute writer method with validation
264
+ # @param [Object] name Value to be assigned
265
+ def name=(name)
266
+ if name.nil?
267
+ fail ArgumentError, 'name cannot be nil'
268
+ end
269
+
270
+ if name.to_s.length > 255
271
+ fail ArgumentError, 'invalid value for "name", the character length must be smaller than or equal to 255.'
272
+ end
273
+
274
+ if name.to_s.length < 1
275
+ fail ArgumentError, 'invalid value for "name", the character length must be great than or equal to 1.'
276
+ end
277
+
278
+ @name = name
279
+ end
280
+
281
+ # Custom attribute writer method with validation
282
+ # @param [Object] postal_code Value to be assigned
283
+ def postal_code=(postal_code)
284
+ if postal_code.nil?
285
+ fail ArgumentError, 'postal_code cannot be nil'
286
+ end
287
+
288
+ if postal_code.to_s.length > 20
289
+ fail ArgumentError, 'invalid value for "postal_code", the character length must be smaller than or equal to 20.'
290
+ end
291
+
292
+ @postal_code = postal_code
293
+ end
294
+
295
+ # Custom attribute writer method with validation
296
+ # @param [Object] state_province Value to be assigned
297
+ def state_province=(state_province)
298
+ if state_province.nil?
299
+ fail ArgumentError, 'state_province cannot be nil'
300
+ end
301
+
302
+ if state_province.to_s.length > 100
303
+ fail ArgumentError, 'invalid value for "state_province", the character length must be smaller than or equal to 100.'
304
+ end
305
+
306
+ @state_province = state_province
307
+ end
308
+
309
+ # Checks equality by comparing each attribute.
310
+ # @param [Object] Object to be compared
311
+ def ==(o)
312
+ return true if self.equal?(o)
313
+ self.class == o.class &&
314
+ boundary == o.boundary &&
315
+ city == o.city &&
316
+ country == o.country &&
317
+ county == o.county &&
318
+ description == o.description &&
319
+ district == o.district &&
320
+ name == o.name &&
321
+ postal_code == o.postal_code &&
322
+ state_province == o.state_province
323
+ end
324
+
325
+ # @see the `==` method
326
+ # @param [Object] Object to be compared
327
+ def eql?(o)
328
+ self == o
329
+ end
330
+
331
+ # Calculates hash code according to all attributes.
332
+ # @return [Integer] Hash code
333
+ def hash
334
+ [boundary, city, country, county, description, district, name, postal_code, state_province].hash
335
+ end
336
+
337
+ # Builds the object from hash
338
+ # @param [Hash] attributes Model attributes in the form of hash
339
+ # @return [Object] Returns the model itself
340
+ def self.build_from_hash(attributes)
341
+ return nil unless attributes.is_a?(Hash)
342
+ attributes = attributes.transform_keys(&:to_sym)
343
+ transformed_hash = {}
344
+ openapi_types.each_pair do |key, type|
345
+ if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil?
346
+ transformed_hash["#{key}"] = nil
347
+ elsif type =~ /\AArray<(.*)>/i
348
+ # check to ensure the input is an array given that the attribute
349
+ # is documented as an array but the input is not
350
+ if attributes[attribute_map[key]].is_a?(Array)
351
+ transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) }
352
+ end
353
+ elsif !attributes[attribute_map[key]].nil?
354
+ transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]])
355
+ end
356
+ end
357
+ new(transformed_hash)
358
+ end
359
+
360
+ # Deserializes the data based on type
361
+ # @param string type Data type
362
+ # @param string value Value to be deserialized
363
+ # @return [Object] Deserialized data
364
+ def self._deserialize(type, value)
365
+ case type.to_sym
366
+ when :Time
367
+ Time.parse(value)
368
+ when :Date
369
+ Date.parse(value)
370
+ when :String
371
+ value.to_s
372
+ when :Integer
373
+ value.to_i
374
+ when :Float
375
+ value.to_f
376
+ when :Boolean
377
+ if value.to_s =~ /\A(true|t|yes|y|1)\z/i
378
+ true
379
+ else
380
+ false
381
+ end
382
+ when :Object
383
+ # generic object (usually a Hash), return directly
384
+ value
385
+ when /\AArray<(?<inner_type>.+)>\z/
386
+ inner_type = Regexp.last_match[:inner_type]
387
+ value.map { |v| _deserialize(inner_type, v) }
388
+ when /\AHash<(?<k_type>.+?), (?<v_type>.+)>\z/
389
+ k_type = Regexp.last_match[:k_type]
390
+ v_type = Regexp.last_match[:v_type]
391
+ {}.tap do |hash|
392
+ value.each do |k, v|
393
+ hash[_deserialize(k_type, k)] = _deserialize(v_type, v)
394
+ end
395
+ end
396
+ else # model
397
+ # models (e.g. Pet) or oneOf
398
+ klass = Crisphive.const_get(type)
399
+ klass.respond_to?(:openapi_any_of) || klass.respond_to?(:openapi_one_of) ? klass.build(value) : klass.build_from_hash(value)
400
+ end
401
+ end
402
+
403
+ # Returns the string representation of the object
404
+ # @return [String] String presentation of the object
405
+ def to_s
406
+ to_hash.to_s
407
+ end
408
+
409
+ # to_body is an alias to to_hash (backward compatibility)
410
+ # @return [Hash] Returns the object in the form of hash
411
+ def to_body
412
+ to_hash
413
+ end
414
+
415
+ # Returns the object in the form of hash
416
+ # @return [Hash] Returns the object in the form of hash
417
+ def to_hash
418
+ hash = {}
419
+ self.class.attribute_map.each_pair do |attr, param|
420
+ value = self.send(attr)
421
+ if value.nil?
422
+ is_nullable = self.class.openapi_nullable.include?(attr)
423
+ next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
424
+ end
425
+
426
+ hash[param] = _to_hash(value)
427
+ end
428
+ hash
429
+ end
430
+
431
+ # Outputs non-array value in the form of hash
432
+ # For object, use to_hash. Otherwise, just return the value
433
+ # @param [Object] value Any valid value
434
+ # @return [Hash] Returns the value in the form of hash
435
+ def _to_hash(value)
436
+ if value.is_a?(Array)
437
+ value.compact.map { |v| _to_hash(v) }
438
+ elsif value.is_a?(Hash)
439
+ {}.tap do |hash|
440
+ value.each { |k, v| hash[k] = _to_hash(v) }
441
+ end
442
+ elsif value.respond_to? :to_hash
443
+ value.to_hash
444
+ else
445
+ value
446
+ end
447
+ end
448
+
449
+ end
450
+
451
+ end