lutaml-model 0.6.7 → 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/.github/workflows/dependent-repos-todo.json +7 -0
- data/.github/workflows/dependent-repos.json +17 -9
- data/.rubocop_todo.yml +18 -33
- data/README.adoc +4380 -2557
- data/lib/lutaml/model/attribute.rb +94 -15
- data/lib/lutaml/model/choice.rb +7 -0
- data/lib/lutaml/model/comparable_model.rb +48 -9
- data/lib/lutaml/model/error/collection_count_out_of_range_error.rb +1 -1
- data/lib/lutaml/model/error/polymorphic_error.rb +9 -0
- data/lib/lutaml/model/error.rb +1 -0
- data/lib/lutaml/model/mapping/json_mapping.rb +17 -0
- data/lib/lutaml/model/{key_value_mapping.rb → mapping/key_value_mapping.rb} +58 -14
- data/lib/lutaml/model/{key_value_mapping_rule.rb → mapping/key_value_mapping_rule.rb} +18 -2
- data/lib/lutaml/model/mapping/mapping_rule.rb +299 -0
- data/lib/lutaml/model/mapping/toml_mapping.rb +25 -0
- data/lib/lutaml/model/{xml_mapping.rb → mapping/xml_mapping.rb} +97 -15
- data/lib/lutaml/model/{xml_mapping_rule.rb → mapping/xml_mapping_rule.rb} +20 -3
- data/lib/lutaml/model/mapping/yaml_mapping.rb +17 -0
- data/lib/lutaml/model/mapping.rb +14 -0
- data/lib/lutaml/model/schema/xml_compiler.rb +15 -15
- data/lib/lutaml/model/sequence.rb +2 -2
- data/lib/lutaml/model/serialize.rb +247 -97
- data/lib/lutaml/model/type/date.rb +1 -1
- data/lib/lutaml/model/type/date_time.rb +2 -2
- data/lib/lutaml/model/type/hash.rb +1 -1
- data/lib/lutaml/model/type/time.rb +2 -2
- data/lib/lutaml/model/type/time_without_date.rb +2 -2
- data/lib/lutaml/model/uninitialized_class.rb +64 -0
- data/lib/lutaml/model/utils.rb +14 -0
- data/lib/lutaml/model/validation.rb +1 -0
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/model/xml_adapter/nokogiri_adapter.rb +1 -1
- data/lib/lutaml/model/xml_adapter/oga_adapter.rb +1 -1
- data/lib/lutaml/model/xml_adapter/ox_adapter.rb +1 -1
- data/lib/lutaml/model/xml_adapter/xml_document.rb +38 -17
- data/lib/lutaml/model/xml_adapter/xml_element.rb +17 -7
- data/lib/lutaml/model.rb +1 -0
- data/spec/benchmarks/xml_parsing_benchmark_spec.rb +3 -3
- data/spec/fixtures/person.rb +5 -5
- data/spec/lutaml/model/attribute_spec.rb +37 -1
- data/spec/lutaml/model/cdata_spec.rb +2 -2
- data/spec/lutaml/model/collection_spec.rb +50 -2
- data/spec/lutaml/model/comparable_model_spec.rb +92 -27
- data/spec/lutaml/model/defaults_spec.rb +1 -1
- data/spec/lutaml/model/enum_spec.rb +1 -1
- data/spec/lutaml/model/group_spec.rb +316 -14
- data/spec/lutaml/model/key_value_mapping_spec.rb +41 -3
- data/spec/lutaml/model/polymorphic_spec.rb +348 -0
- data/spec/lutaml/model/render_empty_spec.rb +194 -0
- data/spec/lutaml/model/render_nil_spec.rb +206 -22
- data/spec/lutaml/model/simple_model_spec.rb +9 -9
- data/spec/lutaml/model/value_map_spec.rb +240 -0
- data/spec/lutaml/model/xml/namespace/nested_with_explicit_namespace_spec.rb +85 -0
- data/spec/lutaml/model/xml/xml_element_spec.rb +93 -0
- data/spec/lutaml/model/xml_mapping_rule_spec.rb +102 -2
- data/spec/lutaml/model/xml_mapping_spec.rb +45 -3
- data/spec/sample_model_spec.rb +3 -3
- metadata +20 -8
- data/lib/lutaml/model/mapping_rule.rb +0 -109
@@ -0,0 +1,348 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module PolymorphicSpec
|
4
|
+
module Base
|
5
|
+
class Reference < Lutaml::Model::Serializable
|
6
|
+
attribute :_class, :string, polymorphic_class: true
|
7
|
+
attribute :name, :string
|
8
|
+
|
9
|
+
xml do
|
10
|
+
map_attribute "reference-type", to: :_class, polymorphic_map: {
|
11
|
+
"document-ref" => "PolymorphicSpec::Base::DocumentReference",
|
12
|
+
"anchor-ref" => "PolymorphicSpec::Base::AnchorReference",
|
13
|
+
}
|
14
|
+
map_element "name", to: :name
|
15
|
+
end
|
16
|
+
|
17
|
+
key_value do
|
18
|
+
map "_class", to: :_class, polymorphic_map: {
|
19
|
+
"Document" => "PolymorphicSpec::Base::DocumentReference",
|
20
|
+
"Anchor" => "PolymorphicSpec::Base::AnchorReference",
|
21
|
+
}
|
22
|
+
map "name", to: :name
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class DocumentReference < Reference
|
27
|
+
attribute :document_id, :string
|
28
|
+
|
29
|
+
xml do
|
30
|
+
map_element "document_id", to: :document_id
|
31
|
+
end
|
32
|
+
|
33
|
+
key_value do
|
34
|
+
map "document_id", to: :document_id
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class AnchorReference < Reference
|
39
|
+
attribute :anchor_id, :string
|
40
|
+
|
41
|
+
xml do
|
42
|
+
map_element "anchor_id", to: :anchor_id
|
43
|
+
end
|
44
|
+
|
45
|
+
key_value do
|
46
|
+
map "anchor_id", to: :anchor_id
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class ReferenceSet < Lutaml::Model::Serializable
|
51
|
+
attribute :references, Reference, collection: true, polymorphic: [
|
52
|
+
DocumentReference,
|
53
|
+
AnchorReference,
|
54
|
+
]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
module Child
|
59
|
+
# Case: If we have no access to the base class and we need to
|
60
|
+
# define polymorphism in the sub-classes.
|
61
|
+
class Reference < Lutaml::Model::Serializable
|
62
|
+
attribute :name, :string
|
63
|
+
|
64
|
+
xml do
|
65
|
+
map_element "name", to: :name
|
66
|
+
end
|
67
|
+
|
68
|
+
key_value do
|
69
|
+
map "name", to: :name
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class DocumentReference < Reference
|
74
|
+
attribute :_class, :string
|
75
|
+
attribute :document_id, :string
|
76
|
+
|
77
|
+
xml do
|
78
|
+
map_element "document_id", to: :document_id
|
79
|
+
map_attribute "_class", to: :_class
|
80
|
+
end
|
81
|
+
|
82
|
+
key_value do
|
83
|
+
map "document_id", to: :document_id
|
84
|
+
map "_class", to: :_class
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
class AnchorReference < Reference
|
89
|
+
attribute :_class, :string
|
90
|
+
attribute :anchor_id, :string
|
91
|
+
|
92
|
+
xml do
|
93
|
+
map_element "anchor_id", to: :anchor_id
|
94
|
+
map_attribute "_class", to: :_class
|
95
|
+
end
|
96
|
+
|
97
|
+
key_value do
|
98
|
+
map "anchor_id", to: :anchor_id
|
99
|
+
map "_class", to: :_class
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
class ReferenceSet < Lutaml::Model::Serializable
|
104
|
+
attribute :references, Reference, collection: true, polymorphic: [
|
105
|
+
DocumentReference,
|
106
|
+
AnchorReference,
|
107
|
+
]
|
108
|
+
|
109
|
+
xml do
|
110
|
+
root "ReferenceSet"
|
111
|
+
|
112
|
+
map_element "references", to: :references, polymorphic: {
|
113
|
+
# This refers to the attribute in the polymorphic model, you need
|
114
|
+
# to specify the attribute name (which is specified in the sub-classed model).
|
115
|
+
attribute: "_class",
|
116
|
+
class_map: {
|
117
|
+
"document-ref" => "PolymorphicSpec::Child::DocumentReference",
|
118
|
+
"anchor-ref" => "PolymorphicSpec::Child::AnchorReference",
|
119
|
+
},
|
120
|
+
}
|
121
|
+
end
|
122
|
+
|
123
|
+
key_value do
|
124
|
+
map "references", to: :references, polymorphic: {
|
125
|
+
attribute: "_class",
|
126
|
+
class_map: {
|
127
|
+
"Document" => "PolymorphicSpec::Child::DocumentReference",
|
128
|
+
"Anchor" => "PolymorphicSpec::Child::AnchorReference",
|
129
|
+
},
|
130
|
+
}
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
RSpec.describe "Polymorphic" do
|
137
|
+
context "when defined in base class" do
|
138
|
+
context "when key_value formats" do
|
139
|
+
let(:reference_set) do
|
140
|
+
PolymorphicSpec::Base::ReferenceSet.new(
|
141
|
+
references: [
|
142
|
+
PolymorphicSpec::Base::DocumentReference.new(
|
143
|
+
_class: "Document",
|
144
|
+
document_id: "book:tbtd",
|
145
|
+
name: "The Tibetan Book of the Dead",
|
146
|
+
),
|
147
|
+
PolymorphicSpec::Base::AnchorReference.new(
|
148
|
+
_class: "Anchor",
|
149
|
+
anchor_id: "book:tbtd:anchor-1",
|
150
|
+
name: "Chapter 1",
|
151
|
+
),
|
152
|
+
],
|
153
|
+
)
|
154
|
+
end
|
155
|
+
|
156
|
+
let(:yaml) do
|
157
|
+
<<~YAML
|
158
|
+
---
|
159
|
+
references:
|
160
|
+
- _class: Document
|
161
|
+
name: The Tibetan Book of the Dead
|
162
|
+
document_id: book:tbtd
|
163
|
+
- _class: Anchor
|
164
|
+
name: Chapter 1
|
165
|
+
anchor_id: book:tbtd:anchor-1
|
166
|
+
YAML
|
167
|
+
end
|
168
|
+
|
169
|
+
let(:parsed_yaml) do
|
170
|
+
PolymorphicSpec::Base::ReferenceSet.from_yaml(yaml)
|
171
|
+
end
|
172
|
+
|
173
|
+
it "deserializes correctly" do
|
174
|
+
expect(parsed_yaml).to eq(reference_set)
|
175
|
+
end
|
176
|
+
|
177
|
+
it "serializes correctly" do
|
178
|
+
expect(parsed_yaml.to_yaml).to eq(yaml)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
context "when XML format" do
|
183
|
+
let(:reference_set) do
|
184
|
+
PolymorphicSpec::Base::ReferenceSet.new(
|
185
|
+
references: [
|
186
|
+
PolymorphicSpec::Base::DocumentReference.new(
|
187
|
+
_class: "document-ref",
|
188
|
+
document_id: "book:tbtd",
|
189
|
+
name: "The Tibetan Book of the Dead",
|
190
|
+
),
|
191
|
+
PolymorphicSpec::Base::AnchorReference.new(
|
192
|
+
_class: "anchor-ref",
|
193
|
+
anchor_id: "book:tbtd:anchor-1",
|
194
|
+
name: "Chapter 1",
|
195
|
+
),
|
196
|
+
],
|
197
|
+
)
|
198
|
+
end
|
199
|
+
|
200
|
+
let(:xml) do
|
201
|
+
<<~XML
|
202
|
+
<ReferenceSet>
|
203
|
+
<references reference-type="document-ref">
|
204
|
+
<name>The Tibetan Book of the Dead</name>
|
205
|
+
<document_id>book:tbtd</document_id>
|
206
|
+
</references>
|
207
|
+
<references reference-type="anchor-ref">
|
208
|
+
<name>Chapter 1</name>
|
209
|
+
<anchor_id>book:tbtd:anchor-1</anchor_id>
|
210
|
+
</references>
|
211
|
+
</ReferenceSet>
|
212
|
+
XML
|
213
|
+
end
|
214
|
+
|
215
|
+
let(:parsed_xml) do
|
216
|
+
PolymorphicSpec::Base::ReferenceSet.from_xml(xml)
|
217
|
+
end
|
218
|
+
|
219
|
+
it "deserializes correctly" do
|
220
|
+
expect(parsed_xml).to eq(reference_set)
|
221
|
+
end
|
222
|
+
|
223
|
+
it "serializes correctly" do
|
224
|
+
expect(parsed_xml.to_xml.strip).to be_equivalent_to(xml.strip)
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
context "when defined in child class" do
|
230
|
+
context "when key_value formats" do
|
231
|
+
let(:reference_set) do
|
232
|
+
PolymorphicSpec::Base::ReferenceSet.new(
|
233
|
+
references: [
|
234
|
+
PolymorphicSpec::Base::DocumentReference.new(
|
235
|
+
_class: "Document",
|
236
|
+
document_id: "book:tbtd",
|
237
|
+
name: "The Tibetan Book of the Dead",
|
238
|
+
),
|
239
|
+
PolymorphicSpec::Base::AnchorReference.new(
|
240
|
+
_class: "Anchor",
|
241
|
+
anchor_id: "book:tbtd:anchor-1",
|
242
|
+
name: "Chapter 1",
|
243
|
+
),
|
244
|
+
],
|
245
|
+
)
|
246
|
+
end
|
247
|
+
|
248
|
+
let(:yaml) do
|
249
|
+
<<~YAML
|
250
|
+
---
|
251
|
+
references:
|
252
|
+
- _class: Document
|
253
|
+
name: The Tibetan Book of the Dead
|
254
|
+
document_id: book:tbtd
|
255
|
+
- _class: Anchor
|
256
|
+
name: Chapter 1
|
257
|
+
anchor_id: book:tbtd:anchor-1
|
258
|
+
YAML
|
259
|
+
end
|
260
|
+
|
261
|
+
let(:parsed_yaml) do
|
262
|
+
PolymorphicSpec::Base::ReferenceSet.from_yaml(yaml)
|
263
|
+
end
|
264
|
+
|
265
|
+
it "deserializes correctly" do
|
266
|
+
expect(parsed_yaml).to eq(reference_set)
|
267
|
+
end
|
268
|
+
|
269
|
+
it "serializes correctly" do
|
270
|
+
expect(parsed_yaml.to_yaml).to eq(yaml)
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
context "when XML format" do
|
275
|
+
let(:reference_set) do
|
276
|
+
PolymorphicSpec::Child::ReferenceSet.new(
|
277
|
+
references: [
|
278
|
+
PolymorphicSpec::Child::DocumentReference.new(
|
279
|
+
_class: "document-ref",
|
280
|
+
document_id: "book:tbtd",
|
281
|
+
name: "The Tibetan Book of the Dead",
|
282
|
+
),
|
283
|
+
PolymorphicSpec::Child::AnchorReference.new(
|
284
|
+
_class: "anchor-ref",
|
285
|
+
anchor_id: "book:tbtd:anchor-1",
|
286
|
+
name: "Chapter 1",
|
287
|
+
),
|
288
|
+
],
|
289
|
+
)
|
290
|
+
end
|
291
|
+
|
292
|
+
let(:invalid_ref) do
|
293
|
+
PolymorphicSpec::Child::ReferenceSet.new(
|
294
|
+
references: [
|
295
|
+
PolymorphicSpec::Child::DocumentReference.new(
|
296
|
+
_class: "document-ref",
|
297
|
+
document_id: "book:tbtd",
|
298
|
+
name: "The Tibetan Book of the Dead",
|
299
|
+
),
|
300
|
+
PolymorphicSpec::Base::AnchorReference.new(
|
301
|
+
_class: "anchor-ref",
|
302
|
+
anchor_id: "book:tbtd:anchor-1",
|
303
|
+
name: "Chapter 1",
|
304
|
+
),
|
305
|
+
],
|
306
|
+
)
|
307
|
+
end
|
308
|
+
|
309
|
+
let(:xml) do
|
310
|
+
<<~XML
|
311
|
+
<ReferenceSet>
|
312
|
+
<references _class="document-ref">
|
313
|
+
<name>The Tibetan Book of the Dead</name>
|
314
|
+
<document_id>book:tbtd</document_id>
|
315
|
+
</references>
|
316
|
+
<references _class="anchor-ref">
|
317
|
+
<name>Chapter 1</name>
|
318
|
+
<anchor_id>book:tbtd:anchor-1</anchor_id>
|
319
|
+
</references>
|
320
|
+
</ReferenceSet>
|
321
|
+
XML
|
322
|
+
end
|
323
|
+
|
324
|
+
let(:parsed_xml) do
|
325
|
+
PolymorphicSpec::Child::ReferenceSet.from_xml(xml)
|
326
|
+
end
|
327
|
+
|
328
|
+
it "deserializes correctly" do
|
329
|
+
expect(parsed_xml).to eq(reference_set)
|
330
|
+
end
|
331
|
+
|
332
|
+
it "serializes correctly" do
|
333
|
+
expect(parsed_xml.to_xml.strip).to be_equivalent_to(xml.strip)
|
334
|
+
end
|
335
|
+
|
336
|
+
it "does not raises error for valid polymorphic class" do
|
337
|
+
expect { reference_set.validate! }.not_to raise_error
|
338
|
+
end
|
339
|
+
|
340
|
+
it "raises error if polymorphic class is not in list" do
|
341
|
+
expect { invalid_ref.validate! }.to raise_error(Lutaml::Model::ValidationError) do |error|
|
342
|
+
expect(error).to include(Lutaml::Model::PolymorphicError)
|
343
|
+
expect(error.error_messages).to include("PolymorphicSpec::Base::AnchorReference not in [PolymorphicSpec::Child::DocumentReference, PolymorphicSpec::Child::AnchorReference]")
|
344
|
+
end
|
345
|
+
end
|
346
|
+
end
|
347
|
+
end
|
348
|
+
end
|
@@ -0,0 +1,194 @@
|
|
1
|
+
module RenderEmptySpec
|
2
|
+
class DefaultModel < Lutaml::Model::Serializable
|
3
|
+
attribute :items, :string, collection: true
|
4
|
+
|
5
|
+
xml do
|
6
|
+
root "default-model"
|
7
|
+
map_element "items", to: :items
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class EmptyInitModel < Lutaml::Model::Serializable
|
12
|
+
attribute :items, :string, collection: true, initialize_empty: true
|
13
|
+
|
14
|
+
xml do
|
15
|
+
root "empty-init-model"
|
16
|
+
map_element "items", to: :items
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class OmitEmptyModel < Lutaml::Model::Serializable
|
21
|
+
attribute :items, :string, collection: true
|
22
|
+
|
23
|
+
xml do
|
24
|
+
root "omit-empty-model"
|
25
|
+
map_element "items", to: :items, render_empty: :omit
|
26
|
+
end
|
27
|
+
|
28
|
+
key_value do
|
29
|
+
map "items", to: :items, render_empty: :omit
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class ExplicitEmptyModel < Lutaml::Model::Serializable
|
34
|
+
attribute :items, :string, collection: true
|
35
|
+
|
36
|
+
key_value do
|
37
|
+
map "items", to: :items, render_empty: :as_empty
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class ExplicitBlankModel < Lutaml::Model::Serializable
|
42
|
+
attribute :items, :string, collection: true
|
43
|
+
|
44
|
+
xml do
|
45
|
+
map_element "items", to: :items, render_empty: :as_blank
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class ExplicitNilModel < Lutaml::Model::Serializable
|
50
|
+
attribute :items, :string, collection: true
|
51
|
+
|
52
|
+
xml do
|
53
|
+
root "explicit-nil-model"
|
54
|
+
map_element "items", to: :items, render_empty: :as_nil
|
55
|
+
end
|
56
|
+
|
57
|
+
yaml do
|
58
|
+
map "items", to: :items, render_empty: :as_nil
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
RSpec.describe "RenderEmptySpec" do
|
64
|
+
describe "Collection States" do
|
65
|
+
context "with default behavior (initialize_empty: false)" do
|
66
|
+
it "defaults to nil" do
|
67
|
+
model = RenderEmptySpec::DefaultModel.new
|
68
|
+
expect(model.items).to be_nil
|
69
|
+
expect(model.to_xml).to eq("<default-model/>")
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context "with initialize_empty: true" do
|
74
|
+
it "defaults to empty array" do
|
75
|
+
model = RenderEmptySpec::EmptyInitModel.new
|
76
|
+
expect(model.items).to eq([])
|
77
|
+
expect(model.to_xml).to eq("<empty-init-model/>")
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "render_empty option" do
|
83
|
+
context "when :omit" do
|
84
|
+
let(:model) do
|
85
|
+
RenderEmptySpec::OmitEmptyModel.new(items: [])
|
86
|
+
end
|
87
|
+
|
88
|
+
it "omits empty collections in XML" do
|
89
|
+
expect(model.to_xml).not_to include("<items")
|
90
|
+
end
|
91
|
+
|
92
|
+
it "omits empty collections in YAML" do
|
93
|
+
expect(model.to_yaml.strip).to eq("--- {}")
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context "when :as_empty" do
|
98
|
+
let(:model) do
|
99
|
+
RenderEmptySpec::ExplicitEmptyModel.new(items: [])
|
100
|
+
end
|
101
|
+
|
102
|
+
let(:parsed) do
|
103
|
+
RenderEmptySpec::ExplicitEmptyModel.from_yaml(yaml)
|
104
|
+
end
|
105
|
+
|
106
|
+
let(:yaml) do
|
107
|
+
<<~YAML
|
108
|
+
---
|
109
|
+
items: []
|
110
|
+
YAML
|
111
|
+
end
|
112
|
+
|
113
|
+
it "renders explicit empty collection" do
|
114
|
+
expect(model.to_yaml).to eq(yaml)
|
115
|
+
end
|
116
|
+
|
117
|
+
it "sets empty values while deserialize" do
|
118
|
+
expect(parsed.items).to eq([])
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context "when :as_blank" do
|
123
|
+
let(:model) do
|
124
|
+
RenderEmptySpec::ExplicitBlankModel.new(items: [])
|
125
|
+
end
|
126
|
+
|
127
|
+
let(:parsed) do
|
128
|
+
RenderEmptySpec::ExplicitBlankModel.from_xml(xml)
|
129
|
+
end
|
130
|
+
|
131
|
+
let(:xml) do
|
132
|
+
<<~XML
|
133
|
+
<explicit-blank-model>
|
134
|
+
<items/>
|
135
|
+
</explicit-blank-model>
|
136
|
+
XML
|
137
|
+
end
|
138
|
+
|
139
|
+
it "creates blank element from empty collections" do
|
140
|
+
expect(model.to_xml).to include("<items/>")
|
141
|
+
end
|
142
|
+
|
143
|
+
it "sets blank values while deserialize" do
|
144
|
+
expect(parsed.items).to eq([])
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
context "when :as_nil" do
|
149
|
+
let(:model) do
|
150
|
+
RenderEmptySpec::ExplicitNilModel.new(items: [])
|
151
|
+
end
|
152
|
+
|
153
|
+
describe "XML" do
|
154
|
+
let(:xml) do
|
155
|
+
<<~XML
|
156
|
+
<explicit-nil-model>
|
157
|
+
<items xsi:nil="true"/>
|
158
|
+
</explicit-nil-model>
|
159
|
+
XML
|
160
|
+
end
|
161
|
+
|
162
|
+
let(:parsed) do
|
163
|
+
RenderEmptySpec::ExplicitNilModel.from_xml(xml)
|
164
|
+
end
|
165
|
+
|
166
|
+
it "renders explicit nil" do
|
167
|
+
expect(model.to_xml).to include('<items xsi:nil="true"/>')
|
168
|
+
end
|
169
|
+
|
170
|
+
it "sets nil values while deserializing" do
|
171
|
+
expect(parsed.items).to eq([])
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
describe "YAML" do
|
176
|
+
let(:yaml) do
|
177
|
+
<<~YAML
|
178
|
+
---
|
179
|
+
items: []
|
180
|
+
YAML
|
181
|
+
end
|
182
|
+
|
183
|
+
it "renders explicit nil in YAML" do
|
184
|
+
expect(model.to_yaml).to include("items:")
|
185
|
+
end
|
186
|
+
|
187
|
+
it "sets nil values while deserializing YAML" do
|
188
|
+
model = RenderEmptySpec::ExplicitNilModel.from_yaml(yaml)
|
189
|
+
expect(model.items).to eq([])
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|