shale 0.5.0 → 0.7.1
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/CHANGELOG.md +28 -0
- data/LICENSE.txt +1 -1
- data/README.md +357 -34
- data/lib/shale/adapter/json.rb +3 -3
- data/lib/shale/adapter/nokogiri/document.rb +10 -0
- data/lib/shale/adapter/nokogiri/node.rb +1 -1
- data/lib/shale/adapter/nokogiri.rb +6 -5
- data/lib/shale/adapter/ox/document.rb +10 -0
- data/lib/shale/adapter/ox/node.rb +10 -1
- data/lib/shale/adapter/ox.rb +5 -4
- data/lib/shale/adapter/rexml/document.rb +11 -1
- data/lib/shale/adapter/rexml.rb +5 -4
- data/lib/shale/adapter/toml_rb.rb +34 -0
- data/lib/shale/error.rb +27 -5
- data/lib/shale/mapper.rb +59 -7
- data/lib/shale/mapping/descriptor/dict.rb +12 -1
- data/lib/shale/mapping/descriptor/xml.rb +12 -2
- data/lib/shale/mapping/dict.rb +26 -2
- data/lib/shale/mapping/xml.rb +52 -6
- data/lib/shale/schema/json_generator.rb +1 -3
- data/lib/shale/schema/xml_compiler.rb +1 -1
- data/lib/shale/schema/xml_generator/import.rb +2 -2
- data/lib/shale/schema/xml_generator.rb +4 -6
- data/lib/shale/type/complex.rb +498 -84
- data/lib/shale/type/date.rb +2 -2
- data/lib/shale/type/time.rb +2 -2
- data/lib/shale/type/value.rb +38 -9
- data/lib/shale/version.rb +1 -1
- data/lib/shale.rb +14 -0
- data/shale.gemspec +2 -2
- metadata +5 -4
data/lib/shale/type/complex.rb
CHANGED
@@ -11,40 +11,80 @@ module Shale
|
|
11
11
|
# @api private
|
12
12
|
class Complex < Value
|
13
13
|
class << self
|
14
|
-
%i[hash json yaml].each do |format|
|
14
|
+
%i[hash json yaml toml].each do |format|
|
15
15
|
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
16
|
-
# Convert Hash to Object using Hash/JSON/YAML mapping
|
16
|
+
# Convert Hash to Object using Hash/JSON/YAML/TOML mapping
|
17
17
|
#
|
18
18
|
# @param [Hash] hash Hash to convert
|
19
|
+
# @param [Array<Symbol>] only
|
20
|
+
# @param [Array<Symbol>] except
|
21
|
+
# @param [any] context
|
19
22
|
#
|
20
|
-
# @return [
|
23
|
+
# @return [model instance]
|
21
24
|
#
|
22
25
|
# @api public
|
23
|
-
def of_#{format}(hash)
|
24
|
-
instance = new
|
26
|
+
def of_#{format}(hash, only: nil, except: nil, context: nil)
|
27
|
+
instance = model.new
|
28
|
+
|
29
|
+
attributes
|
30
|
+
.values
|
31
|
+
.select { |attr| attr.default }
|
32
|
+
.each { |attr| instance.send(attr.setter, attr.default.call) }
|
25
33
|
|
26
34
|
mapping_keys = #{format}_mapping.keys
|
27
35
|
|
36
|
+
only = to_partial_render_attributes(only)
|
37
|
+
except = to_partial_render_attributes(except)
|
38
|
+
|
28
39
|
hash.each do |key, value|
|
29
40
|
mapping = mapping_keys[key]
|
30
41
|
next unless mapping
|
31
42
|
|
32
43
|
if mapping.method_from
|
33
|
-
|
44
|
+
mapper = new
|
45
|
+
|
46
|
+
if mapper.method(mapping.method_from).arity == 3
|
47
|
+
mapper.send(mapping.method_from, instance, value, context)
|
48
|
+
else
|
49
|
+
mapper.send(mapping.method_from, instance, value)
|
50
|
+
end
|
34
51
|
else
|
35
52
|
attribute = attributes[mapping.attribute]
|
36
53
|
next unless attribute
|
37
54
|
|
55
|
+
if only
|
56
|
+
attribute_only = only[attribute.name]
|
57
|
+
next unless only.key?(attribute.name)
|
58
|
+
end
|
59
|
+
|
60
|
+
if except
|
61
|
+
attribute_except = except[attribute.name]
|
62
|
+
next if except.key?(attribute.name) && attribute_except.nil?
|
63
|
+
end
|
64
|
+
|
38
65
|
if value.nil?
|
39
66
|
instance.send(attribute.setter, nil)
|
40
67
|
elsif attribute.collection?
|
41
68
|
[*value].each do |val|
|
42
|
-
|
69
|
+
if val
|
70
|
+
val = attribute.type.of_#{format}(
|
71
|
+
val,
|
72
|
+
only: attribute_only,
|
73
|
+
except: attribute_except,
|
74
|
+
context: context
|
75
|
+
)
|
76
|
+
end
|
77
|
+
|
43
78
|
instance.send(attribute.name) << attribute.type.cast(val)
|
44
79
|
end
|
45
80
|
else
|
46
|
-
val = attribute.type.of_#{format}(
|
47
|
-
|
81
|
+
val = attribute.type.of_#{format}(
|
82
|
+
value,
|
83
|
+
only: attribute_only,
|
84
|
+
except: attribute_except,
|
85
|
+
context: context
|
86
|
+
)
|
87
|
+
instance.send(attribute.setter, attribute.type.cast(val))
|
48
88
|
end
|
49
89
|
end
|
50
90
|
end
|
@@ -52,33 +92,76 @@ module Shale
|
|
52
92
|
instance
|
53
93
|
end
|
54
94
|
|
55
|
-
# Convert Object to Hash using Hash/JSON/YAML mapping
|
95
|
+
# Convert Object to Hash using Hash/JSON/YAML/TOML mapping
|
56
96
|
#
|
57
|
-
# @param [
|
97
|
+
# @param [any] instance Object to convert
|
98
|
+
# @param [Array<Symbol>] only
|
99
|
+
# @param [Array<Symbol>] except
|
100
|
+
# @param [any] context
|
101
|
+
#
|
102
|
+
# @raise [IncorrectModelError]
|
58
103
|
#
|
59
104
|
# @return [Hash]
|
60
105
|
#
|
61
106
|
# @api public
|
62
|
-
def as_#{format}(instance)
|
107
|
+
def as_#{format}(instance, only: nil, except: nil, context: nil)
|
108
|
+
unless instance.is_a?(model)
|
109
|
+
msg = "argument is a '\#{instance.class}' but should be a '\#{model}'"
|
110
|
+
raise IncorrectModelError, msg
|
111
|
+
end
|
112
|
+
|
63
113
|
hash = {}
|
64
114
|
|
65
|
-
|
115
|
+
only = to_partial_render_attributes(only)
|
116
|
+
except = to_partial_render_attributes(except)
|
117
|
+
|
118
|
+
#{format}_mapping.keys.each_value do |mapping|
|
66
119
|
if mapping.method_to
|
67
|
-
|
120
|
+
mapper = new
|
121
|
+
|
122
|
+
if mapper.method(mapping.method_to).arity == 3
|
123
|
+
mapper.send(mapping.method_to, instance, hash, context)
|
124
|
+
else
|
125
|
+
mapper.send(mapping.method_to, instance, hash)
|
126
|
+
end
|
68
127
|
else
|
69
|
-
attribute =
|
128
|
+
attribute = attributes[mapping.attribute]
|
70
129
|
next unless attribute
|
71
130
|
|
131
|
+
if only
|
132
|
+
attribute_only = only[attribute.name]
|
133
|
+
next unless only.key?(attribute.name)
|
134
|
+
end
|
135
|
+
|
136
|
+
if except
|
137
|
+
attribute_except = except[attribute.name]
|
138
|
+
next if except.key?(attribute.name) && attribute_except.nil?
|
139
|
+
end
|
140
|
+
|
72
141
|
value = instance.send(attribute.name)
|
73
142
|
|
74
143
|
if value.nil?
|
75
|
-
hash[mapping.name] = nil
|
144
|
+
hash[mapping.name] = nil if mapping.render_nil?
|
76
145
|
elsif attribute.collection?
|
77
|
-
hash[mapping.name] = [*value].map do |
|
78
|
-
|
146
|
+
hash[mapping.name] = [*value].map do |val|
|
147
|
+
if val
|
148
|
+
attribute.type.as_#{format}(
|
149
|
+
val,
|
150
|
+
only: attribute_only,
|
151
|
+
except: attribute_except,
|
152
|
+
context: context
|
153
|
+
)
|
154
|
+
else
|
155
|
+
val
|
156
|
+
end
|
79
157
|
end
|
80
158
|
else
|
81
|
-
hash[mapping.name] = attribute.type.as_#{format}(
|
159
|
+
hash[mapping.name] = attribute.type.as_#{format}(
|
160
|
+
value,
|
161
|
+
only: attribute_only,
|
162
|
+
except: attribute_except,
|
163
|
+
context: context
|
164
|
+
)
|
82
165
|
end
|
83
166
|
end
|
84
167
|
end
|
@@ -95,81 +178,187 @@ module Shale
|
|
95
178
|
# Convert JSON to Object
|
96
179
|
#
|
97
180
|
# @param [String] json JSON to convert
|
181
|
+
# @param [Array<Symbol>] only
|
182
|
+
# @param [Array<Symbol>] except
|
183
|
+
# @param [any] context
|
98
184
|
#
|
99
|
-
# @return [
|
185
|
+
# @return [model instance]
|
100
186
|
#
|
101
187
|
# @api public
|
102
|
-
def from_json(json)
|
103
|
-
of_json(
|
188
|
+
def from_json(json, only: nil, except: nil, context: nil)
|
189
|
+
of_json(
|
190
|
+
Shale.json_adapter.load(json),
|
191
|
+
only: only,
|
192
|
+
except: except,
|
193
|
+
context: context
|
194
|
+
)
|
104
195
|
end
|
105
196
|
|
106
197
|
# Convert Object to JSON
|
107
198
|
#
|
108
|
-
# @param [
|
109
|
-
# @param [Array<Symbol>]
|
199
|
+
# @param [model instance] instance Object to convert
|
200
|
+
# @param [Array<Symbol>] only
|
201
|
+
# @param [Array<Symbol>] except
|
202
|
+
# @param [any] context
|
203
|
+
# @param [true, false] pretty
|
110
204
|
#
|
111
205
|
# @return [String]
|
112
206
|
#
|
113
207
|
# @api public
|
114
|
-
def to_json(instance,
|
115
|
-
Shale.json_adapter.dump(
|
208
|
+
def to_json(instance, only: nil, except: nil, context: nil, pretty: false)
|
209
|
+
Shale.json_adapter.dump(
|
210
|
+
as_json(instance, only: only, except: except, context: context),
|
211
|
+
pretty: pretty
|
212
|
+
)
|
116
213
|
end
|
117
214
|
|
118
215
|
# Convert YAML to Object
|
119
216
|
#
|
120
217
|
# @param [String] yaml YAML to convert
|
218
|
+
# @param [Array<Symbol>] only
|
219
|
+
# @param [Array<Symbol>] except
|
220
|
+
# @param [any] context
|
121
221
|
#
|
122
|
-
# @return [
|
222
|
+
# @return [model instance]
|
123
223
|
#
|
124
224
|
# @api public
|
125
|
-
def from_yaml(yaml)
|
126
|
-
of_yaml(
|
225
|
+
def from_yaml(yaml, only: nil, except: nil, context: nil)
|
226
|
+
of_yaml(
|
227
|
+
Shale.yaml_adapter.load(yaml),
|
228
|
+
only: only,
|
229
|
+
except: except,
|
230
|
+
context: context
|
231
|
+
)
|
127
232
|
end
|
128
233
|
|
129
234
|
# Convert Object to YAML
|
130
235
|
#
|
131
|
-
# @param [
|
236
|
+
# @param [model instance] instance Object to convert
|
237
|
+
# @param [Array<Symbol>] only
|
238
|
+
# @param [Array<Symbol>] except
|
239
|
+
# @param [any] context
|
240
|
+
#
|
241
|
+
# @return [String]
|
242
|
+
#
|
243
|
+
# @api public
|
244
|
+
def to_yaml(instance, only: nil, except: nil, context: nil)
|
245
|
+
Shale.yaml_adapter.dump(
|
246
|
+
as_yaml(instance, only: only, except: except, context: context)
|
247
|
+
)
|
248
|
+
end
|
249
|
+
|
250
|
+
# Convert TOML to Object
|
251
|
+
#
|
252
|
+
# @param [String] toml TOML to convert
|
253
|
+
# @param [Array<Symbol>] only
|
254
|
+
# @param [Array<Symbol>] except
|
255
|
+
# @param [any] context
|
256
|
+
#
|
257
|
+
# @return [model instance]
|
258
|
+
#
|
259
|
+
# @api public
|
260
|
+
def from_toml(toml, only: nil, except: nil, context: nil)
|
261
|
+
validate_toml_adapter
|
262
|
+
of_toml(
|
263
|
+
Shale.toml_adapter.load(toml),
|
264
|
+
only: only,
|
265
|
+
except: except,
|
266
|
+
context: context
|
267
|
+
)
|
268
|
+
end
|
269
|
+
|
270
|
+
# Convert Object to TOML
|
271
|
+
#
|
272
|
+
# @param [model instance] instance Object to convert
|
273
|
+
# @param [Array<Symbol>] only
|
274
|
+
# @param [Array<Symbol>] except
|
275
|
+
# @param [any] context
|
132
276
|
#
|
133
277
|
# @return [String]
|
134
278
|
#
|
135
279
|
# @api public
|
136
|
-
def
|
137
|
-
|
280
|
+
def to_toml(instance, only: nil, except: nil, context: nil)
|
281
|
+
validate_toml_adapter
|
282
|
+
Shale.toml_adapter.dump(
|
283
|
+
as_toml(instance, only: only, except: except, context: context)
|
284
|
+
)
|
138
285
|
end
|
139
286
|
|
140
287
|
# Convert XML document to Object
|
141
288
|
#
|
142
|
-
# @param [Shale::Adapter::<XML adapter>::Node]
|
289
|
+
# @param [Shale::Adapter::<XML adapter>::Node] element
|
290
|
+
# @param [Array<Symbol>] only
|
291
|
+
# @param [Array<Symbol>] except
|
292
|
+
# @param [any] context
|
143
293
|
#
|
144
|
-
# @return [
|
294
|
+
# @return [model instance]
|
145
295
|
#
|
146
296
|
# @api public
|
147
|
-
def of_xml(element)
|
148
|
-
instance = new
|
297
|
+
def of_xml(element, only: nil, except: nil, context: nil)
|
298
|
+
instance = model.new
|
299
|
+
|
300
|
+
attributes
|
301
|
+
.values
|
302
|
+
.select { |attr| attr.default }
|
303
|
+
.each { |attr| instance.send(attr.setter, attr.default.call) }
|
304
|
+
|
305
|
+
only = to_partial_render_attributes(only)
|
306
|
+
except = to_partial_render_attributes(except)
|
149
307
|
|
150
308
|
element.attributes.each do |key, value|
|
151
309
|
mapping = xml_mapping.attributes[key.to_s]
|
152
310
|
next unless mapping
|
153
311
|
|
154
312
|
if mapping.method_from
|
155
|
-
|
313
|
+
mapper = new
|
314
|
+
|
315
|
+
if mapper.method(mapping.method_from).arity == 3
|
316
|
+
mapper.send(mapping.method_from, instance, value, context)
|
317
|
+
else
|
318
|
+
mapper.send(mapping.method_from, instance, value)
|
319
|
+
end
|
156
320
|
else
|
157
321
|
attribute = attributes[mapping.attribute]
|
158
322
|
next unless attribute
|
159
323
|
|
324
|
+
next if only && !only.key?(attribute.name)
|
325
|
+
next if except&.key?(attribute.name)
|
326
|
+
|
160
327
|
if attribute.collection?
|
161
328
|
instance.send(attribute.name) << attribute.type.cast(value)
|
162
329
|
else
|
163
|
-
instance.send(attribute.setter, value)
|
330
|
+
instance.send(attribute.setter, attribute.type.cast(value))
|
164
331
|
end
|
165
332
|
end
|
166
333
|
end
|
167
334
|
|
168
|
-
|
169
|
-
|
335
|
+
content_mapping = xml_mapping.content
|
336
|
+
|
337
|
+
if content_mapping
|
338
|
+
if content_mapping.method_from
|
339
|
+
mapper = new
|
340
|
+
|
341
|
+
if mapper.method(content_mapping.method_from).arity == 3
|
342
|
+
mapper.send(content_mapping.method_from, instance, element, context)
|
343
|
+
else
|
344
|
+
mapper.send(content_mapping.method_from, instance, element)
|
345
|
+
end
|
346
|
+
else
|
347
|
+
attribute = attributes[content_mapping.attribute]
|
348
|
+
|
349
|
+
if attribute
|
350
|
+
skip = false
|
170
351
|
|
171
|
-
|
172
|
-
|
352
|
+
# rubocop:disable Metrics/BlockNesting
|
353
|
+
skip = true if only && !only.key?(attribute.name)
|
354
|
+
skip = true if except&.key?(attribute.name)
|
355
|
+
|
356
|
+
unless skip
|
357
|
+
value = attribute.type.of_xml(element)
|
358
|
+
instance.send(attribute.setter, attribute.type.cast(value))
|
359
|
+
end
|
360
|
+
# rubocop:enable Metrics/BlockNesting
|
361
|
+
end
|
173
362
|
end
|
174
363
|
end
|
175
364
|
|
@@ -178,16 +367,38 @@ module Shale
|
|
178
367
|
next unless mapping
|
179
368
|
|
180
369
|
if mapping.method_from
|
181
|
-
|
370
|
+
mapper = new
|
371
|
+
|
372
|
+
if mapper.method(mapping.method_from).arity == 3
|
373
|
+
mapper.send(mapping.method_from, instance, node, context)
|
374
|
+
else
|
375
|
+
mapper.send(mapping.method_from, instance, node)
|
376
|
+
end
|
182
377
|
else
|
183
378
|
attribute = attributes[mapping.attribute]
|
184
379
|
next unless attribute
|
185
380
|
|
381
|
+
if only
|
382
|
+
attribute_only = only[attribute.name]
|
383
|
+
next unless only.key?(attribute.name)
|
384
|
+
end
|
385
|
+
|
386
|
+
if except
|
387
|
+
attribute_except = except[attribute.name]
|
388
|
+
next if except.key?(attribute.name) && attribute_except.nil?
|
389
|
+
end
|
390
|
+
|
391
|
+
value = attribute.type.of_xml(
|
392
|
+
node,
|
393
|
+
only: attribute_only,
|
394
|
+
except: attribute_except,
|
395
|
+
context: context
|
396
|
+
)
|
397
|
+
|
186
398
|
if attribute.collection?
|
187
|
-
value = attribute.type.of_xml(node)
|
188
399
|
instance.send(attribute.name) << attribute.type.cast(value)
|
189
400
|
else
|
190
|
-
instance.send(attribute.setter, attribute.type.
|
401
|
+
instance.send(attribute.setter, attribute.type.cast(value))
|
191
402
|
end
|
192
403
|
end
|
193
404
|
end
|
@@ -198,79 +409,198 @@ module Shale
|
|
198
409
|
# Convert XML to Object
|
199
410
|
#
|
200
411
|
# @param [String] xml XML to convert
|
412
|
+
# @param [Array<Symbol>] only
|
413
|
+
# @param [Array<Symbol>] except
|
414
|
+
# @param [any] context
|
201
415
|
#
|
202
416
|
# @raise [AdapterError]
|
203
417
|
#
|
204
|
-
# @return [
|
418
|
+
# @return [model instance]
|
205
419
|
#
|
206
420
|
# @api public
|
207
|
-
def from_xml(xml)
|
421
|
+
def from_xml(xml, only: nil, except: nil, context: nil)
|
208
422
|
validate_xml_adapter
|
209
|
-
of_xml(
|
423
|
+
of_xml(
|
424
|
+
Shale.xml_adapter.load(xml),
|
425
|
+
only: only,
|
426
|
+
except: except,
|
427
|
+
context: context
|
428
|
+
)
|
210
429
|
end
|
211
430
|
|
212
431
|
# Convert Object to XML document
|
213
432
|
#
|
214
|
-
# @param [
|
433
|
+
# @param [any] instance Object to convert
|
215
434
|
# @param [String, nil] node_name XML node name
|
216
435
|
# @param [Shale::Adapter::<xml adapter>::Document, nil] doc Object to convert
|
436
|
+
# @param [Array<Symbol>] only
|
437
|
+
# @param [Array<Symbol>] except
|
438
|
+
# @param [any] context
|
439
|
+
#
|
440
|
+
# @raise [IncorrectModelError]
|
217
441
|
#
|
218
442
|
# @return [::REXML::Document, ::Nokogiri::Document, ::Ox::Document]
|
219
443
|
#
|
220
444
|
# @api public
|
221
|
-
def as_xml(
|
445
|
+
def as_xml(
|
446
|
+
instance,
|
447
|
+
node_name = nil,
|
448
|
+
doc = nil,
|
449
|
+
_cdata = nil,
|
450
|
+
only: nil,
|
451
|
+
except: nil,
|
452
|
+
context: nil
|
453
|
+
)
|
454
|
+
unless instance.is_a?(model)
|
455
|
+
msg = "argument is a '#{instance.class}' but should be a '#{model}'"
|
456
|
+
raise IncorrectModelError, msg
|
457
|
+
end
|
458
|
+
|
222
459
|
unless doc
|
223
460
|
doc = Shale.xml_adapter.create_document
|
224
|
-
|
461
|
+
|
462
|
+
element = as_xml(
|
463
|
+
instance,
|
464
|
+
xml_mapping.prefixed_root,
|
465
|
+
doc,
|
466
|
+
only: only,
|
467
|
+
except: except,
|
468
|
+
context: context
|
469
|
+
)
|
470
|
+
doc.add_element(doc.doc, element)
|
471
|
+
|
225
472
|
return doc.doc
|
226
473
|
end
|
227
474
|
|
228
475
|
element = doc.create_element(node_name)
|
229
|
-
|
476
|
+
|
477
|
+
doc.add_namespace(
|
478
|
+
xml_mapping.default_namespace.prefix,
|
479
|
+
xml_mapping.default_namespace.name
|
480
|
+
)
|
481
|
+
|
482
|
+
only = to_partial_render_attributes(only)
|
483
|
+
except = to_partial_render_attributes(except)
|
230
484
|
|
231
485
|
xml_mapping.attributes.each_value do |mapping|
|
232
486
|
if mapping.method_to
|
233
|
-
|
487
|
+
mapper = new
|
488
|
+
|
489
|
+
if mapper.method(mapping.method_to).arity == 4
|
490
|
+
mapper.send(mapping.method_to, instance, element, doc, context)
|
491
|
+
else
|
492
|
+
mapper.send(mapping.method_to, instance, element, doc)
|
493
|
+
end
|
234
494
|
else
|
235
|
-
attribute =
|
495
|
+
attribute = attributes[mapping.attribute]
|
236
496
|
next unless attribute
|
237
497
|
|
498
|
+
next if only && !only.key?(attribute.name)
|
499
|
+
next if except&.key?(attribute.name)
|
500
|
+
|
238
501
|
value = instance.send(attribute.name)
|
239
|
-
next if value.nil?
|
240
502
|
|
241
|
-
|
242
|
-
|
503
|
+
if mapping.render_nil? || !value.nil?
|
504
|
+
doc.add_namespace(mapping.namespace.prefix, mapping.namespace.name)
|
505
|
+
doc.add_attribute(element, mapping.prefixed_name, value)
|
506
|
+
end
|
243
507
|
end
|
244
508
|
end
|
245
509
|
|
246
|
-
|
247
|
-
attribute = instance.class.attributes[xml_mapping.content]
|
510
|
+
content_mapping = xml_mapping.content
|
248
511
|
|
249
|
-
|
250
|
-
|
251
|
-
|
512
|
+
if content_mapping
|
513
|
+
if content_mapping.method_to
|
514
|
+
mapper = new
|
515
|
+
|
516
|
+
if mapper.method(content_mapping.method_to).arity == 4
|
517
|
+
mapper.send(content_mapping.method_to, instance, element, doc, context)
|
518
|
+
else
|
519
|
+
mapper.send(content_mapping.method_to, instance, element, doc)
|
520
|
+
end
|
521
|
+
else
|
522
|
+
attribute = attributes[content_mapping.attribute]
|
523
|
+
|
524
|
+
if attribute
|
525
|
+
skip = false
|
526
|
+
|
527
|
+
# rubocop:disable Metrics/BlockNesting
|
528
|
+
skip = true if only && !only.key?(attribute.name)
|
529
|
+
skip = true if except&.key?(attribute.name)
|
530
|
+
|
531
|
+
unless skip
|
532
|
+
value = instance.send(attribute.name)
|
533
|
+
|
534
|
+
if content_mapping.cdata
|
535
|
+
doc.create_cdata(value.to_s, element)
|
536
|
+
else
|
537
|
+
doc.add_text(element, value.to_s)
|
538
|
+
end
|
539
|
+
end
|
540
|
+
# rubocop:enable Metrics/BlockNesting
|
541
|
+
end
|
252
542
|
end
|
253
543
|
end
|
254
544
|
|
255
545
|
xml_mapping.elements.each_value do |mapping|
|
256
546
|
if mapping.method_to
|
257
|
-
|
547
|
+
mapper = new
|
548
|
+
|
549
|
+
if mapper.method(mapping.method_to).arity == 4
|
550
|
+
mapper.send(mapping.method_to, instance, element, doc, context)
|
551
|
+
else
|
552
|
+
mapper.send(mapping.method_to, instance, element, doc)
|
553
|
+
end
|
258
554
|
else
|
259
|
-
attribute =
|
555
|
+
attribute = attributes[mapping.attribute]
|
260
556
|
next unless attribute
|
261
557
|
|
558
|
+
if only
|
559
|
+
attribute_only = only[attribute.name]
|
560
|
+
next unless only.key?(attribute.name)
|
561
|
+
end
|
562
|
+
|
563
|
+
if except
|
564
|
+
attribute_except = except[attribute.name]
|
565
|
+
next if except.key?(attribute.name) && attribute_except.nil?
|
566
|
+
end
|
567
|
+
|
262
568
|
value = instance.send(attribute.name)
|
263
|
-
next if value.nil?
|
264
569
|
|
265
|
-
|
570
|
+
if mapping.render_nil? || !value.nil?
|
571
|
+
doc.add_namespace(mapping.namespace.prefix, mapping.namespace.name)
|
572
|
+
end
|
266
573
|
|
267
|
-
if
|
574
|
+
if value.nil?
|
575
|
+
if mapping.render_nil?
|
576
|
+
child = doc.create_element(mapping.prefixed_name)
|
577
|
+
doc.add_element(element, child)
|
578
|
+
end
|
579
|
+
elsif attribute.collection?
|
268
580
|
[*value].each do |v|
|
269
581
|
next if v.nil?
|
270
|
-
|
582
|
+
child = attribute.type.as_xml(
|
583
|
+
v,
|
584
|
+
mapping.prefixed_name,
|
585
|
+
doc,
|
586
|
+
mapping.cdata,
|
587
|
+
only: attribute_only,
|
588
|
+
except: attribute_except,
|
589
|
+
context: context
|
590
|
+
)
|
591
|
+
doc.add_element(element, child)
|
271
592
|
end
|
272
593
|
else
|
273
|
-
|
594
|
+
child = attribute.type.as_xml(
|
595
|
+
value,
|
596
|
+
mapping.prefixed_name,
|
597
|
+
doc,
|
598
|
+
mapping.cdata,
|
599
|
+
only: attribute_only,
|
600
|
+
except: attribute_except,
|
601
|
+
context: context
|
602
|
+
)
|
603
|
+
doc.add_element(element, child)
|
274
604
|
end
|
275
605
|
end
|
276
606
|
end
|
@@ -280,69 +610,153 @@ module Shale
|
|
280
610
|
|
281
611
|
# Convert Object to XML
|
282
612
|
#
|
283
|
-
# @param [
|
284
|
-
# @param [Array<Symbol>]
|
613
|
+
# @param [model instance] instance Object to convert
|
614
|
+
# @param [Array<Symbol>] only
|
615
|
+
# @param [Array<Symbol>] except
|
616
|
+
# @param [any] context
|
617
|
+
# @param [true, false] pretty
|
618
|
+
# @param [true, false] declaration
|
285
619
|
#
|
286
620
|
# @raise [AdapterError]
|
287
621
|
#
|
288
622
|
# @return [String]
|
289
623
|
#
|
290
624
|
# @api public
|
291
|
-
def to_xml(
|
625
|
+
def to_xml(
|
626
|
+
instance,
|
627
|
+
only: nil,
|
628
|
+
except: nil,
|
629
|
+
context: nil,
|
630
|
+
pretty: false,
|
631
|
+
declaration: false
|
632
|
+
)
|
292
633
|
validate_xml_adapter
|
293
|
-
Shale.xml_adapter.dump(
|
634
|
+
Shale.xml_adapter.dump(
|
635
|
+
as_xml(instance, only: only, except: except, context: context),
|
636
|
+
pretty: pretty,
|
637
|
+
declaration: declaration
|
638
|
+
)
|
294
639
|
end
|
295
640
|
|
296
641
|
private
|
297
642
|
|
643
|
+
# Validate TOML adapter
|
644
|
+
#
|
645
|
+
# @raise [AdapterError]
|
646
|
+
#
|
647
|
+
# @api private
|
648
|
+
def validate_toml_adapter
|
649
|
+
raise AdapterError, TOML_ADAPTER_NOT_SET_MESSAGE unless Shale.toml_adapter
|
650
|
+
end
|
651
|
+
|
298
652
|
# Validate XML adapter
|
299
653
|
#
|
300
654
|
# @raise [AdapterError]
|
301
655
|
#
|
302
656
|
# @api private
|
303
657
|
def validate_xml_adapter
|
304
|
-
raise AdapterError,
|
658
|
+
raise AdapterError, XML_ADAPTER_NOT_SET_MESSAGE unless Shale.xml_adapter
|
659
|
+
end
|
660
|
+
|
661
|
+
# Convert array with attributes to a hash
|
662
|
+
#
|
663
|
+
# @param [Array] ary
|
664
|
+
#
|
665
|
+
# @return [Hash, nil]
|
666
|
+
#
|
667
|
+
# @api private
|
668
|
+
def to_partial_render_attributes(ary)
|
669
|
+
return unless ary
|
670
|
+
|
671
|
+
ary.each_with_object([]) do |e, obj|
|
672
|
+
if e.is_a?(Hash)
|
673
|
+
obj.push(*e.to_a)
|
674
|
+
else
|
675
|
+
obj.push([e, nil])
|
676
|
+
end
|
677
|
+
end.to_h
|
305
678
|
end
|
306
679
|
end
|
307
680
|
|
308
681
|
# Convert Object to Hash
|
309
682
|
#
|
683
|
+
# @param [Array<Symbol>] only
|
684
|
+
# @param [Array<Symbol>] except
|
685
|
+
# @param [any] context
|
686
|
+
#
|
310
687
|
# @return [Hash]
|
311
688
|
#
|
312
689
|
# @api public
|
313
|
-
def to_hash
|
314
|
-
self.class.to_hash(self)
|
690
|
+
def to_hash(only: nil, except: nil, context: nil)
|
691
|
+
self.class.to_hash(self, only: only, except: except, context: context)
|
315
692
|
end
|
316
693
|
|
317
694
|
# Convert Object to JSON
|
318
695
|
#
|
319
|
-
# @param [Array<Symbol>]
|
696
|
+
# @param [Array<Symbol>] only
|
697
|
+
# @param [Array<Symbol>] except
|
698
|
+
# @param [any] context
|
699
|
+
# @param [true, false] pretty
|
320
700
|
#
|
321
701
|
# @return [String]
|
322
702
|
#
|
323
703
|
# @api public
|
324
|
-
def to_json(
|
325
|
-
self.class.to_json(
|
704
|
+
def to_json(only: nil, except: nil, context: nil, pretty: false)
|
705
|
+
self.class.to_json(
|
706
|
+
self,
|
707
|
+
only: only,
|
708
|
+
except: except,
|
709
|
+
context: context,
|
710
|
+
pretty: pretty
|
711
|
+
)
|
326
712
|
end
|
327
713
|
|
328
714
|
# Convert Object to YAML
|
329
715
|
#
|
716
|
+
# @param [Array<Symbol>] only
|
717
|
+
# @param [Array<Symbol>] except
|
718
|
+
# @param [any] context
|
719
|
+
#
|
720
|
+
# @return [String]
|
721
|
+
#
|
722
|
+
# @api public
|
723
|
+
def to_yaml(only: nil, except: nil, context: nil)
|
724
|
+
self.class.to_yaml(self, only: only, except: except, context: context)
|
725
|
+
end
|
726
|
+
|
727
|
+
# Convert Object to TOML
|
728
|
+
#
|
729
|
+
# @param [Array<Symbol>] only
|
730
|
+
# @param [Array<Symbol>] except
|
731
|
+
# @param [any] context
|
732
|
+
#
|
330
733
|
# @return [String]
|
331
734
|
#
|
332
735
|
# @api public
|
333
|
-
def
|
334
|
-
self.class.
|
736
|
+
def to_toml(only: nil, except: nil, context: nil)
|
737
|
+
self.class.to_toml(self, only: only, except: except, context: context)
|
335
738
|
end
|
336
739
|
|
337
740
|
# Convert Object to XML
|
338
741
|
#
|
339
|
-
# @param [Array<Symbol>]
|
742
|
+
# @param [Array<Symbol>] only
|
743
|
+
# @param [Array<Symbol>] except
|
744
|
+
# @param [any] context
|
745
|
+
# @param [true, false] pretty
|
746
|
+
# @param [true, false] declaration
|
340
747
|
#
|
341
748
|
# @return [String]
|
342
749
|
#
|
343
750
|
# @api public
|
344
|
-
def to_xml(
|
345
|
-
self.class.to_xml(
|
751
|
+
def to_xml(only: nil, except: nil, context: nil, pretty: false, declaration: false)
|
752
|
+
self.class.to_xml(
|
753
|
+
self,
|
754
|
+
only: only,
|
755
|
+
except: except,
|
756
|
+
context: context,
|
757
|
+
pretty: pretty,
|
758
|
+
declaration: declaration
|
759
|
+
)
|
346
760
|
end
|
347
761
|
end
|
348
762
|
end
|