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