lutaml-model 0.3.3 → 0.3.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c1c49d91f74f3454b6a0e2aaf34bfef142630fa77e98a509535b53b156f603e7
4
- data.tar.gz: 12880e7b701bf68c2a77efad6148daeac040a1956f1f1e1a0d790657c79f346c
3
+ metadata.gz: d80c5eb43638cf5d690c6c59db2fba76ddb8e2fc7252117a3c7933bc566b2607
4
+ data.tar.gz: d75c694c330c017500dcceb604aaa889633dadb53c7766a4b6310ee3aef1725e
5
5
  SHA512:
6
- metadata.gz: '08020dbbadaea322601ce9c0536cf3a49aeaa44679d8caf278995d0f7b1c41ba12761897db7f54390bb1288c84ccedc6a0a45bee980926fecca18927a17c8de7'
7
- data.tar.gz: 363806235f0d4308f127d84590d1b2d2bf2af5adafd27974fa6a8600f5e67afac6efc27f3ee810eea95265d6764b6f4538672f18c5c9a3e243c31f236595fe21
6
+ metadata.gz: fc9ed09d01c0c19b4038af7de38c3c458f7c200f7b5ae509f4e4cfc2d3abe116ad862168b7d2ffef16e0d5205c67b3a54226b8b826f9859a72ec5d32da00545e
7
+ data.tar.gz: b4b8348522112cce9236dc7989f30b42df22ac04d6a7459b2fff6ad6c6dc7018d4bd88e97ec9f83ab8b2dcf6d92938d18fcdc882914240d3d53fb16e0ba116d3
data/.rubocop_todo.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2024-08-16 03:28:27 UTC using RuboCop version 1.65.1.
3
+ # on 2024-08-16 11:07:41 UTC using RuboCop version 1.65.1.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
@@ -14,24 +14,41 @@ Gemspec/RequireMFA:
14
14
  Exclude:
15
15
  - 'lutaml-model.gemspec'
16
16
 
17
- # Offense count: 32
17
+ # Offense count: 76
18
18
  # This cop supports safe autocorrection (--autocorrect).
19
19
  # Configuration parameters: Max, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns.
20
20
  # URISchemes: http, https
21
21
  Layout/LineLength:
22
22
  Exclude:
23
+ - 'lib/lutaml/model/cli.rb'
24
+ - 'lib/lutaml/model/comparable_model.rb'
23
25
  - 'lib/lutaml/model/serialize.rb'
24
26
  - 'lib/lutaml/model/type.rb'
25
27
  - 'lib/lutaml/model/xml_adapter/nokogiri_adapter.rb'
26
28
  - 'lib/lutaml/model/xml_adapter/ox_adapter.rb'
27
29
  - 'lib/lutaml/model/xml_adapter/xml_document.rb'
30
+ - 'spec/lutaml/model/comparable_model_spec.rb'
28
31
  - 'spec/lutaml/model/delegation_spec.rb'
32
+ - 'spec/lutaml/model/schema/json_schema_spec.rb'
29
33
  - 'spec/lutaml/model/serializable_spec.rb'
30
34
 
31
- # Offense count: 20
35
+ # Offense count: 4
36
+ # Configuration parameters: AllowedMethods.
37
+ # AllowedMethods: enums
38
+ Lint/ConstantDefinitionInBlock:
39
+ Exclude:
40
+ - 'spec/lutaml/model/schema/json_schema_spec.rb'
41
+ - 'spec/lutaml/model/schema/relaxng_schema_spec.rb'
42
+ - 'spec/lutaml/model/schema/xsd_schema_spec.rb'
43
+ - 'spec/lutaml/model/schema/yaml_schema_spec.rb'
44
+
45
+ # Offense count: 31
32
46
  # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
33
47
  Metrics/AbcSize:
34
48
  Exclude:
49
+ - 'lib/lutaml/model/comparable_model.rb'
50
+ - 'lib/lutaml/model/schema/relaxng_schema.rb'
51
+ - 'lib/lutaml/model/schema/xsd_schema.rb'
35
52
  - 'lib/lutaml/model/serialize.rb'
36
53
  - 'lib/lutaml/model/type.rb'
37
54
  - 'lib/lutaml/model/xml_adapter/nokogiri_adapter.rb'
@@ -44,17 +61,18 @@ Metrics/AbcSize:
44
61
  Metrics/BlockLength:
45
62
  Max: 30
46
63
 
47
- # Offense count: 19
64
+ # Offense count: 23
48
65
  # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
49
66
  Metrics/CyclomaticComplexity:
50
67
  Exclude:
68
+ - 'lib/lutaml/model/comparable_model.rb'
51
69
  - 'lib/lutaml/model/serialize.rb'
52
70
  - 'lib/lutaml/model/type.rb'
53
71
  - 'lib/lutaml/model/xml_adapter/nokogiri_adapter.rb'
54
72
  - 'lib/lutaml/model/xml_adapter/ox_adapter.rb'
55
73
  - 'lib/lutaml/model/xml_adapter/xml_document.rb'
56
74
 
57
- # Offense count: 27
75
+ # Offense count: 38
58
76
  # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
59
77
  Metrics/MethodLength:
60
78
  Max: 41
@@ -64,10 +82,11 @@ Metrics/MethodLength:
64
82
  Metrics/ParameterLists:
65
83
  Max: 9
66
84
 
67
- # Offense count: 17
85
+ # Offense count: 20
68
86
  # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
69
87
  Metrics/PerceivedComplexity:
70
88
  Exclude:
89
+ - 'lib/lutaml/model/comparable_model.rb'
71
90
  - 'lib/lutaml/model/serialize.rb'
72
91
  - 'lib/lutaml/model/type.rb'
73
92
  - 'lib/lutaml/model/xml_adapter/nokogiri_adapter.rb'
@@ -83,10 +102,10 @@ RSpec/ContextWording:
83
102
  - 'spec/lutaml/model/xml_adapter/oga_adapter_spec.rb'
84
103
  - 'spec/lutaml/model/xml_adapter/ox_adapter_spec.rb'
85
104
 
86
- # Offense count: 64
105
+ # Offense count: 70
87
106
  # Configuration parameters: CountAsOne.
88
107
  RSpec/ExampleLength:
89
- Max: 35
108
+ Max: 57
90
109
 
91
110
  # Offense count: 2
92
111
  # Configuration parameters: Max, AllowedIdentifiers, AllowedPatterns.
@@ -94,6 +113,14 @@ RSpec/IndexedLet:
94
113
  Exclude:
95
114
  - 'spec/address_spec.rb'
96
115
 
116
+ # Offense count: 12
117
+ RSpec/LeakyConstantDeclaration:
118
+ Exclude:
119
+ - 'spec/lutaml/model/schema/json_schema_spec.rb'
120
+ - 'spec/lutaml/model/schema/relaxng_schema_spec.rb'
121
+ - 'spec/lutaml/model/schema/xsd_schema_spec.rb'
122
+ - 'spec/lutaml/model/schema/yaml_schema_spec.rb'
123
+
97
124
  # Offense count: 4
98
125
  RSpec/MultipleDescribes:
99
126
  Exclude:
@@ -102,7 +129,7 @@ RSpec/MultipleDescribes:
102
129
  - 'spec/lutaml/model/xml_adapter/xml_namespace_spec.rb'
103
130
  - 'spec/lutaml/model/xml_adapter_spec.rb'
104
131
 
105
- # Offense count: 63
132
+ # Offense count: 69
106
133
  RSpec/MultipleExpectations:
107
134
  Max: 15
108
135
 
@@ -125,3 +152,15 @@ RSpec/SpecFilePathFormat:
125
152
  Exclude:
126
153
  - '**/spec/routing/**/*'
127
154
  - 'spec/lutaml/model/collection_spec.rb'
155
+
156
+ # Offense count: 1
157
+ Security/CompoundHash:
158
+ Exclude:
159
+ - 'lib/lutaml/model/comparable_model.rb'
160
+
161
+ # Offense count: 1
162
+ # Configuration parameters: AllowedMethods.
163
+ # AllowedMethods: respond_to_missing?
164
+ Style/OptionalBooleanParameter:
165
+ Exclude:
166
+ - 'lib/lutaml/model/comparable_model.rb'
data/README.adoc CHANGED
@@ -69,16 +69,18 @@ Or install it yourself as:
69
69
  gem install lutaml-model
70
70
  ----
71
71
 
72
- == Defining a data model class
72
+ == Data model class
73
73
 
74
- === General
74
+ === Definition
75
+
76
+ ==== General
75
77
 
76
78
  There are two ways to define a data model in Lutaml::Model:
77
79
 
78
80
  * Inheriting from the `Lutaml::Model::Serializable` class
79
81
  * Including the `Lutaml::Model::Serialize` module
80
82
 
81
- === Definition through inheritance
83
+ ==== Definition through inheritance
82
84
 
83
85
  The simplest way to define a model is to create a class that inherits from
84
86
  `Lutaml::Model::Serializable`.
@@ -90,13 +92,13 @@ The `attribute` class method is used to define attributes.
90
92
  require 'lutaml/model'
91
93
 
92
94
  class Kiln < Lutaml::Model::Serializable
93
- attribute :brand, Lutaml::Model::Type::String
94
- attribute :capacity, Lutaml::Model::Type::Integer
95
- attribute :temperature, Lutaml::Model::Type::Integer
95
+ attribute :brand, :string
96
+ attribute :capacity, :integer
97
+ attribute :temperature, :integer
96
98
  end
97
99
  ----
98
100
 
99
- === Definition through inclusion
101
+ ==== Definition through inclusion
100
102
 
101
103
  If the model class already has a super class that it inherits from, the model
102
104
  can be extended using the `Lutaml::Model::Serialize` module.
@@ -108,12 +110,38 @@ require 'lutaml/model'
108
110
  class Kiln < SomeSuperClass
109
111
  include Lutaml::Model::Serialize
110
112
 
111
- attribute :brand, Lutaml::Model::Type::String
112
- attribute :capacity, Lutaml::Model::Type::Integer
113
- attribute :temperature, Lutaml::Model::Type::Integer
113
+ attribute :brand, :string
114
+ attribute :capacity, :integer
115
+ attribute :temperature, :integer
114
116
  end
115
117
  ----
116
118
 
119
+
120
+ === Comparison
121
+
122
+ A `Serialize` / `Serializable` object can be compared with another object of the
123
+ same class using the `==` operator. This is implemented through the
124
+ `ComparableModel` module.
125
+
126
+ Two objects are considered equal if they have the same class and all their
127
+ attributes are equal. This behavior differs from the typical Ruby behavior,
128
+ where two objects are considered equal only if they have the same object ID.
129
+
130
+ NOTE: Two `Serialize` objects will have the same `hash` value if they have the
131
+ same class and all their attributes are equal.
132
+
133
+ [source,ruby]
134
+ ----
135
+ > a = Kiln.new(brand: 'Kiln 1', capacity: 100, temperature: 1050)
136
+ > b = Kiln.new(brand: 'Kiln 1', capacity: 100, temperature: 1050)
137
+ > a == b
138
+ > # true
139
+ > a.hash == b.hash
140
+ > # true
141
+ ----
142
+
143
+
144
+
117
145
  == Defining attributes
118
146
 
119
147
  === Supported attribute value types
@@ -160,7 +188,7 @@ class Studio < Lutaml::Model::Serializable
160
188
  # The following are equivalent
161
189
  attribute :location, :string
162
190
  attribute :potter, "String"
163
- attribute :kiln, Lutaml::Model::Type::String
191
+ attribute :kiln, :string
164
192
  end
165
193
  ----
166
194
 
@@ -196,8 +224,8 @@ attribute :name_of_attribute, Type, collection: true
196
224
  [source,ruby]
197
225
  ----
198
226
  class Studio < Lutaml::Model::Serializable
199
- attribute :location, Lutaml::Model::Type::String
200
- attribute :potters, Lutaml::Model::Type::String, collection: true
227
+ attribute :location, :string
228
+ attribute :potters, :string, collection: true
201
229
  end
202
230
  ----
203
231
 
@@ -224,25 +252,85 @@ Syntax:
224
252
  attribute :name_of_attribute, Type, values: [value1, value2, ...]
225
253
  ----
226
254
 
227
- .Using the `values` directive to define acceptable values for an attribute
255
+ The values set inside the `values:` option can be of any type, but they must
256
+ match the type of the attribute. The values are compared using the `==` operator,
257
+ so the type must implement the `==` method.
258
+
259
+ .Using the `values` directive to define acceptable values for an attribute (basic types)
260
+ [example]
261
+ ====
262
+ [source,ruby]
263
+ ----
264
+ class GlazeTechnique < Lutaml::Model::Serializable
265
+ attribute :name, :string, values: ["Celadon", "Raku", "Majolica"]
266
+ end
267
+ ----
268
+
269
+ [source,ruby]
270
+ ----
271
+ > GlazeTechnique.new(name: "Celadon").name
272
+ > # "Celadon"
273
+ > GlazeTechnique.new(name: "Raku").name
274
+ > # "Raku"
275
+ > GlazeTechnique.new(name: "Majolica").name
276
+ > # "Majolica"
277
+ > GlazeTechnique.new(name: "Earthenware").name
278
+ > # Lutaml::Model::InvalidValueError: Invalid value for attribute 'name'
279
+ ----
280
+ ====
281
+
282
+ The values can be Serialize objects, which are compared using the `==`
283
+ and the `hash` methods through the Lutaml::Model::ComparableModel module.
284
+
285
+
286
+ .Using the `values` directive to define acceptable values for an attribute (Serializable objects)
228
287
  [example]
229
288
  ====
230
289
  [source,ruby]
231
290
  ----
232
291
  class Ceramic < Lutaml::Model::Serializable
233
- attribute :type, Lutaml::Model::Type::String,
234
- values: ['Porcelain', 'Earthenware', 'Stoneware']
292
+ attribute :type, :string
293
+ attribute :firing_temperature, :integer
294
+ end
295
+
296
+ class CeramicCollection < Lutaml::Model::Serializable
297
+ attribute :featured_piece,
298
+ Ceramic,
299
+ values: [
300
+ Ceramic.new(type: "Porcelain", firing_temperature: 1300),
301
+ Ceramic.new(type: "Stoneware", firing_temperature: 1200),
302
+ Ceramic.new(type: "Earthenware", firing_temperature: 1000),
303
+ ]
235
304
  end
236
305
  ----
237
306
 
238
307
  [source,ruby]
239
308
  ----
240
- > Ceramic.new(type: 'Porcelain').type
241
- > # "Porcelain"
242
- > Ceramic.new(type: 'Earthenware').type
243
- > # "Earthenware"
244
- > Ceramic.new(type: 'Bone China').type
245
- > # Lutaml::Model::InvalidValueError: Invalid value for attribute 'type'
309
+ > CeramicCollection.new(featured_piece: Ceramic.new(type: "Porcelain", firing_temperature: 1300)).featured_piece
310
+ > # Ceramic:0x0000000104ac7240 @type="Porcelain", @firing_temperature=1300
311
+ > CeramicCollection.new(featured_piece: Ceramic.new(type: "Bone China", firing_temperature: 1300)).featured_piece
312
+ > # Lutaml::Model::InvalidValueError: Invalid value for attribute 'featured_piece'
313
+ ----
314
+ ====
315
+
316
+ Serialize provides a `validate` method that checks if all its attributes have
317
+ valid values. This is necessary for the case when a value is valid at the
318
+ component level, but not accepted at the aggregation level.
319
+
320
+ If a change has been made at the component level (a nested attribute has
321
+ changed), the aggregation level needs to call the `validate` method to verify
322
+ acceptance of the newly updated component.
323
+
324
+ .Using the `validate` method to check if all attributes have valid values
325
+ [example]
326
+ ====
327
+ [source,ruby]
328
+ ----
329
+ > collection = CeramicCollection.new(featured_piece: Ceramic.new(type: "Porcelain", firing_temperature: 1300))
330
+ > collection.featured_piece.firing_temperature = 1400
331
+ > # No error raised in changed nested attribute
332
+ > collection.validate
333
+ > # Lutaml::Model::InvalidValueError: Invalid value for attribute 'featured_piece'
246
334
  ----
247
335
  ====
248
336
 
@@ -266,8 +354,8 @@ attribute :name_of_attribute, Type, default: -> { value }
266
354
  [source,ruby]
267
355
  ----
268
356
  class Glaze < Lutaml::Model::Serializable
269
- attribute :color, Lutaml::Model::Type::String, default: -> { 'Clear' }
270
- attribute :temperature, Lutaml::Model::Type::Integer, default: -> { 1050 }
357
+ attribute :color, :string, default: -> { 'Clear' }
358
+ attribute :temperature, :integer, default: -> { 1050 }
271
359
  end
272
360
  ----
273
361
 
@@ -378,7 +466,7 @@ end
378
466
  [source,ruby]
379
467
  ----
380
468
  class Example < Lutaml::Model::Serializable
381
- attribute :name, Lutaml::Model::Type::String
469
+ attribute :name, :string
382
470
 
383
471
  xml do
384
472
  root 'example'
@@ -458,7 +546,7 @@ The following class will parse the XML snippet below:
458
546
  [source,ruby]
459
547
  ----
460
548
  class Example < Lutaml::Model::Serializable
461
- attribute :value, Lutaml::Model::Type::Integer
549
+ attribute :value, :integer
462
550
 
463
551
  xml do
464
552
  root 'example'
@@ -506,7 +594,7 @@ The following class will parse the XML snippet below:
506
594
  [source,ruby]
507
595
  ----
508
596
  class Example < Lutaml::Model::Serializable
509
- attribute :description, Lutaml::Model::Type::String
597
+ attribute :description, :string
510
598
 
511
599
  xml do
512
600
  root 'example'
@@ -540,9 +628,9 @@ The following class will parse the XML snippet below:
540
628
  [source,ruby]
541
629
  ----
542
630
  class Example < Lutaml::Model::Serializable
543
- attribute :name, Lutaml::Model::Type::String
544
- attribute :description, Lutaml::Model::Type::String
545
- attribute :value, Lutaml::Model::Type::Integer
631
+ attribute :name, :string
632
+ attribute :description, :string
633
+ attribute :value, :integer
546
634
 
547
635
  xml do
548
636
  root 'example'
@@ -590,8 +678,8 @@ end
590
678
  [source,ruby]
591
679
  ----
592
680
  class Ceramic < Lutaml::Model::Serializable
593
- attribute :type, Lutaml::Model::Type::String
594
- attribute :glaze, Lutaml::Model::Type::String
681
+ attribute :type, :string
682
+ attribute :glaze, :string
595
683
 
596
684
  xml do
597
685
  root 'Ceramic'
@@ -644,8 +732,8 @@ In this example, `glz` will be used for `Glaze` if it is added inside the
644
732
  [source,ruby]
645
733
  ----
646
734
  class Glaze < Lutaml::Model::Serializable
647
- attribute :color, Lutaml::Model::Type::String
648
- attribute :temperature, Lutaml::Model::Type::Integer
735
+ attribute :color, :string
736
+ attribute :temperature, :integer
649
737
 
650
738
  xml do
651
739
  root 'Glaze'
@@ -657,7 +745,7 @@ class Glaze < Lutaml::Model::Serializable
657
745
  end
658
746
 
659
747
  class Ceramic < Lutaml::Model::Serializable
660
- attribute :type, Lutaml::Model::Type::String
748
+ attribute :type, :string
661
749
  attribute :glaze, Glaze
662
750
 
663
751
  xml do
@@ -711,9 +799,9 @@ In this example, the `Type` element will inherit the namespace from the root.
711
799
  [source,ruby]
712
800
  ----
713
801
  class Ceramic < Lutaml::Model::Serializable
714
- attribute :type, Lutaml::Model::Type::String
715
- attribute :glaze, Lutaml::Model::Type::String
716
- attribute :color, Lutaml::Model::Type::String
802
+ attribute :type, :string
803
+ attribute :glaze, :string
804
+ attribute :color, :string
717
805
 
718
806
  xml do
719
807
  root 'Ceramic'
@@ -791,8 +879,8 @@ end
791
879
  [source,ruby]
792
880
  ----
793
881
  class Paragraph < Lutaml::Model::Serializable
794
- attribute :bold, Lutaml::Model::Type::String
795
- attribute :italic, Lutaml::Model::Type::String
882
+ attribute :bold, :string
883
+ attribute :italic, :string
796
884
 
797
885
  xml do
798
886
  root 'p', mixed: true
@@ -835,8 +923,8 @@ end
835
923
  [source,ruby]
836
924
  ----
837
925
  class Paragraph < Lutaml::Model::Serializable
838
- attribute :bold, Lutaml::Model::Type::String
839
- attribute :italic, Lutaml::Model::Type::String
926
+ attribute :bold, :string
927
+ attribute :italic, :string
840
928
 
841
929
  xml do
842
930
  root 'p'
@@ -895,8 +983,8 @@ end
895
983
  [source,ruby]
896
984
  ----
897
985
  class Example < Lutaml::Model::Serializable
898
- attribute :name, Lutaml::Model::Type::String
899
- attribute :value, Lutaml::Model::Type::Integer
986
+ attribute :name, :string
987
+ attribute :value, :integer
900
988
 
901
989
  json do
902
990
  map 'name', to: :name
@@ -943,8 +1031,8 @@ by referring to a Lutaml::Model class as an attribute class.
943
1031
  [source,ruby]
944
1032
  ----
945
1033
  class Glaze < Lutaml::Model::Serializable
946
- attribute :color, Lutaml::Model::Type::String
947
- attribute :temperature, Lutaml::Model::Type::Integer
1034
+ attribute :color, :string
1035
+ attribute :temperature, :integer
948
1036
 
949
1037
  json do
950
1038
  map 'color', to: :color
@@ -953,7 +1041,7 @@ class Glaze < Lutaml::Model::Serializable
953
1041
  end
954
1042
 
955
1043
  class Ceramic < Lutaml::Model::Serializable
956
- attribute :type, Lutaml::Model::Type::String
1044
+ attribute :type, :string
957
1045
  attribute :glaze, Glaze
958
1046
 
959
1047
  json do
@@ -983,6 +1071,158 @@ end
983
1071
  ----
984
1072
  ====
985
1073
 
1074
+
1075
+ === Separate serialization model
1076
+
1077
+ The `Serialize` module can be used to define only serialization mappings for a
1078
+ separately defined model (a Ruby class).
1079
+
1080
+ Syntax:
1081
+
1082
+ [source,ruby]
1083
+ ----
1084
+ class Foo < Lutaml::Model::Serializable
1085
+ model {DataModelClass}
1086
+
1087
+ # ...
1088
+ end
1089
+ ----
1090
+
1091
+ [example]
1092
+ .Using the `model` method to define serialization mappings for a separate model
1093
+ ====
1094
+ [source,ruby]
1095
+ ----
1096
+ class Ceramic
1097
+ attr_accessor :type, :glaze
1098
+
1099
+ def name
1100
+ "#{type} with #{glaze}"
1101
+ end
1102
+ end
1103
+
1104
+ class CeramicSerialization < Lutaml::Model::Serializable
1105
+ model Ceramic
1106
+
1107
+ xml do
1108
+ map_element 'type', to: :type
1109
+ map_element 'glaze', to: :glaze
1110
+ end
1111
+ end
1112
+ ----
1113
+
1114
+ [source,ruby]
1115
+ ----
1116
+ > Ceramic.new(type: "Porcelain", glaze: "Clear").name
1117
+ > # "Porcelain with Clear"
1118
+ > CeramicSerialization.from_xml(xml)
1119
+ > #<Ceramic:0x0000000104ac7240 @type="Porcelain", @glaze="Clear">
1120
+ > Ceramic.new(type: "Porcelain", glaze: "Clear").to_xml
1121
+ > #<Ceramic><type>Porcelain</type><glaze>Clear</glaze></Ceramic>
1122
+ ----
1123
+ ====
1124
+
1125
+
1126
+ === Rendering empty attributes and collections
1127
+
1128
+ By default, empty attributes and collections are not rendered in the output.
1129
+
1130
+ To render empty attributes and collections, use the `render_nil` option.
1131
+
1132
+ Syntax:
1133
+
1134
+ [source,ruby]
1135
+ ----
1136
+ xml do
1137
+ map_element 'key_value_model_attribute_name', to: :name_of_attribute, render_nil: true
1138
+ end
1139
+ ----
1140
+
1141
+ [source,ruby]
1142
+ ----
1143
+ json | yaml | toml do
1144
+ map 'key_value_model_attribute_name', to: :name_of_attribute, render_nil: true
1145
+ end
1146
+ ----
1147
+
1148
+ .Using the `render_nil` option to render empty attributes
1149
+ [example]
1150
+ ====
1151
+ [source,ruby]
1152
+ ----
1153
+ class Ceramic < Lutaml::Model::Serializable
1154
+ attribute :type, :string
1155
+ attribute :glaze, :string
1156
+
1157
+ xml do
1158
+ map_element 'type', to: :type, render_nil: true
1159
+ map_element 'glaze', to: :glaze
1160
+ end
1161
+
1162
+ json do
1163
+ map 'type', to: :type, render_nil: true
1164
+ map 'glaze', to: :glaze
1165
+ end
1166
+ end
1167
+ ----
1168
+
1169
+ [source,ruby]
1170
+ ----
1171
+ > Ceramic.new.to_json
1172
+ > # { 'type': null }
1173
+ > Ceramic.new(type: "Porcelain", glaze: "Clear").to_json
1174
+ > # { 'type': 'Porcelain', 'glaze': 'Clear' }
1175
+ ----
1176
+
1177
+ [source,ruby]
1178
+ ----
1179
+ > Ceramic.new.to_xml
1180
+ > # <Ceramic><type></type></Ceramic>
1181
+ > Ceramic.new(type: "Porcelain", glaze: "Clear").to_xml
1182
+ > # <Ceramic><type>Porcelain</type><glaze>Clear</glaze></Ceramic>
1183
+ ----
1184
+ ====
1185
+
1186
+ .Using the `render_nil` option to render empty attribute collections
1187
+ [example]
1188
+ ====
1189
+ [source,ruby]
1190
+ ----
1191
+ class Ceramic < Lutaml::Model::Serializable
1192
+ attribute :type, :string
1193
+ attribute :glazes, :string, collection: true
1194
+
1195
+ xml do
1196
+ map_element 'type', to: :type, render_nil: true
1197
+ map_element 'glazes', to: :glazes, render_nil: true
1198
+ end
1199
+
1200
+ json do
1201
+ map 'type', to: :type, render_nil: true
1202
+ map 'glazes', to: :glazes, render_nil: true
1203
+ end
1204
+ end
1205
+ ----
1206
+
1207
+ [source,ruby]
1208
+ ----
1209
+ > Ceramic.new.to_json
1210
+ > # { 'type': null, 'glazes': [] }
1211
+ > Ceramic.new(type: "Porcelain", glazes: ["Clear"]).to_json
1212
+ > # { 'type': 'Porcelain', 'glazes': ['Clear'] }
1213
+ ----
1214
+
1215
+ [source,ruby]
1216
+ ----
1217
+ > Ceramic.new.to_xml
1218
+ > # <Ceramic><type></type><glazes></glazes></Ceramic>
1219
+ > Ceramic.new(type: "Porcelain", glazes: ["Clear"]).to_xml
1220
+ > # <Ceramic><type>Porcelain</type><glazes>Clear</glazes></Ceramic>
1221
+ ----
1222
+ ====
1223
+
1224
+
1225
+
986
1226
  === Advanced attribute mapping
987
1227
 
988
1228
  ==== Attribute mapping delegation
@@ -1006,8 +1246,8 @@ The following class will parse the JSON snippet below:
1006
1246
  [source,ruby]
1007
1247
  ----
1008
1248
  class Glaze < Lutaml::Model::Serializable
1009
- attribute :color, Lutaml::Model::Type::String
1010
- attribute :temperature, Lutaml::Model::Type::Integer
1249
+ attribute :color, :string
1250
+ attribute :temperature, :integer
1011
1251
 
1012
1252
  json do
1013
1253
  map 'color', to: :color
@@ -1016,7 +1256,7 @@ class Glaze < Lutaml::Model::Serializable
1016
1256
  end
1017
1257
 
1018
1258
  class Ceramic < Lutaml::Model::Serializable
1019
- attribute :type, Lutaml::Model::Type::String
1259
+ attribute :type, :string
1020
1260
  attribute :glaze, Glaze
1021
1261
 
1022
1262
  json do
@@ -1069,8 +1309,8 @@ The following class will parse the JSON snippet below:
1069
1309
  [source,ruby]
1070
1310
  ----
1071
1311
  class CustomCeramic < Lutaml::Model::Serializable
1072
- attribute :name, Lutaml::Model::Type::String
1073
- attribute :size, Lutaml::Model::Type::Integer
1312
+ attribute :name, :string
1313
+ attribute :size, :integer
1074
1314
 
1075
1315
  json do
1076
1316
  map 'name', to: :name, with: { to: :name_to_json, from: :name_from_json }
@@ -1250,9 +1490,9 @@ A model can be defined for this JSON as follows:
1250
1490
  [source,ruby]
1251
1491
  ----
1252
1492
  class Schema < Lutaml::Model::Serializable
1253
- attribute :id, Lutaml::Model::Type::String
1254
- attribute :link, Lutaml::Model::Type::String
1255
- attribute :name, Lutaml::Model::Type::String
1493
+ attribute :id, :string
1494
+ attribute :link, :string
1495
+ attribute :name, :string
1256
1496
  end
1257
1497
 
1258
1498
  class ChildMappingClass < Lutaml::Model::Serializable
data/exe/lutaml-model ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require_relative "../lib/lutaml/model/cli"
6
+
7
+ Lutaml::Model::Cli.start(ARGV)