lutaml-model 0.4.0 → 0.5.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/.rubocop_todo.yml +34 -18
- data/README.adoc +166 -8
- data/lib/lutaml/model/key_value_mapping.rb +0 -1
- data/lib/lutaml/model/key_value_mapping_rule.rb +3 -1
- data/lib/lutaml/model/mapping_rule.rb +14 -2
- data/lib/lutaml/model/serialize.rb +67 -52
- data/lib/lutaml/model/type/decimal.rb +5 -0
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/model/xml_adapter/builder/nokogiri.rb +1 -0
- data/lib/lutaml/model/xml_adapter/builder/oga.rb +180 -0
- data/lib/lutaml/model/xml_adapter/builder/ox.rb +1 -0
- data/lib/lutaml/model/xml_adapter/oga/document.rb +20 -0
- data/lib/lutaml/model/xml_adapter/oga/element.rb +117 -0
- data/lib/lutaml/model/xml_adapter/oga_adapter.rb +77 -44
- data/lib/lutaml/model/xml_adapter/xml_document.rb +11 -9
- data/lib/lutaml/model/xml_mapping.rb +0 -1
- data/lib/lutaml/model/xml_mapping_rule.rb +16 -4
- data/spec/address_spec.rb +1 -0
- data/spec/fixtures/sample_model.rb +7 -0
- data/spec/lutaml/model/custom_model_spec.rb +47 -1
- data/spec/lutaml/model/included_spec.rb +192 -0
- data/spec/lutaml/model/mixed_content_spec.rb +48 -32
- data/spec/lutaml/model/multiple_mapping_spec.rb +329 -0
- data/spec/lutaml/model/ordered_content_spec.rb +1 -1
- data/spec/lutaml/model/render_nil_spec.rb +3 -0
- data/spec/lutaml/model/serializable_spec.rb +1 -1
- data/spec/lutaml/model/type/boolean_spec.rb +62 -0
- data/spec/lutaml/model/xml_adapter/oga_adapter_spec.rb +11 -11
- data/spec/lutaml/model/xml_adapter/xml_namespace_spec.rb +1 -1
- data/spec/lutaml/model/xml_adapter_spec.rb +2 -2
- data/spec/lutaml/model/xml_mapping_spec.rb +24 -9
- data/spec/sample_model_spec.rb +114 -0
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b1472bd6c2746013aba5d315d47dc5e484cfa54f6f537ab5d613b81f4f63109e
|
4
|
+
data.tar.gz: 45c48daa9b4a0f7b98d04bb8174f6cfe298c59564b714b866f838b7d2bf6464b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 94f772a0efbc35332c95fb55729c8d781d4168ff61784af79d2f09388c93263144b378d8485e578f43aeb0386b2c02d4769285c782dffaa2c5d4dd6f0f34fa70
|
7
|
+
data.tar.gz: 4dd7279a62a8835e1f7c908590cc653d693f9a0225a388eda89bfa02cdcc7fb9a934bbf8d273f57d93d9764c86b867ae42a7aab2a87a4322c89698fa207343d0
|
data/.rubocop_todo.yml
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
# This configuration was generated by
|
2
2
|
# `rubocop --auto-gen-config`
|
3
|
-
# on
|
3
|
+
# on 2025-01-07 08:52:47 UTC using RuboCop version 1.69.2.
|
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
|
7
7
|
# versions of RuboCop, may require this file to be generated again.
|
8
8
|
|
9
|
-
# Offense count:
|
9
|
+
# Offense count: 292
|
10
10
|
# This cop supports safe autocorrection (--autocorrect).
|
11
|
-
# Configuration parameters: Max, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns.
|
11
|
+
# Configuration parameters: Max, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings.
|
12
12
|
# URISchemes: http, https
|
13
13
|
Layout/LineLength:
|
14
14
|
Enabled: false
|
@@ -31,7 +31,7 @@ Lint/DuplicateMethods:
|
|
31
31
|
Exclude:
|
32
32
|
- 'lib/lutaml/model/type/float.rb'
|
33
33
|
|
34
|
-
# Offense count:
|
34
|
+
# Offense count: 40
|
35
35
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
|
36
36
|
Metrics/AbcSize:
|
37
37
|
Exclude:
|
@@ -42,18 +42,20 @@ Metrics/AbcSize:
|
|
42
42
|
- 'lib/lutaml/model/schema/xsd_schema.rb'
|
43
43
|
- 'lib/lutaml/model/serialize.rb'
|
44
44
|
- 'lib/lutaml/model/xml_adapter/nokogiri_adapter.rb'
|
45
|
+
- 'lib/lutaml/model/xml_adapter/oga/element.rb'
|
46
|
+
- 'lib/lutaml/model/xml_adapter/oga_adapter.rb'
|
45
47
|
- 'lib/lutaml/model/xml_adapter/ox_adapter.rb'
|
46
48
|
- 'lib/lutaml/model/xml_adapter/xml_document.rb'
|
47
49
|
- 'lib/lutaml/model/xml_mapping.rb'
|
48
50
|
- 'lib/lutaml/model/xml_mapping_rule.rb'
|
49
51
|
|
50
|
-
# Offense count:
|
52
|
+
# Offense count: 9
|
51
53
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode.
|
52
54
|
# AllowedMethods: refine
|
53
55
|
Metrics/BlockLength:
|
54
56
|
Max: 46
|
55
57
|
|
56
|
-
# Offense count:
|
58
|
+
# Offense count: 32
|
57
59
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
58
60
|
Metrics/CyclomaticComplexity:
|
59
61
|
Exclude:
|
@@ -61,21 +63,23 @@ Metrics/CyclomaticComplexity:
|
|
61
63
|
- 'lib/lutaml/model/comparable_model.rb'
|
62
64
|
- 'lib/lutaml/model/serialize.rb'
|
63
65
|
- 'lib/lutaml/model/type/integer.rb'
|
66
|
+
- 'lib/lutaml/model/xml_adapter/builder/oga.rb'
|
64
67
|
- 'lib/lutaml/model/xml_adapter/nokogiri_adapter.rb'
|
68
|
+
- 'lib/lutaml/model/xml_adapter/oga_adapter.rb'
|
65
69
|
- 'lib/lutaml/model/xml_adapter/ox_adapter.rb'
|
66
70
|
- 'lib/lutaml/model/xml_adapter/xml_document.rb'
|
67
71
|
|
68
|
-
# Offense count:
|
72
|
+
# Offense count: 63
|
69
73
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
70
74
|
Metrics/MethodLength:
|
71
|
-
Max:
|
75
|
+
Max: 44
|
72
76
|
|
73
77
|
# Offense count: 7
|
74
78
|
# Configuration parameters: CountKeywordArgs, MaxOptionalParameters.
|
75
79
|
Metrics/ParameterLists:
|
76
|
-
Max:
|
80
|
+
Max: 15
|
77
81
|
|
78
|
-
# Offense count:
|
82
|
+
# Offense count: 30
|
79
83
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
80
84
|
Metrics/PerceivedComplexity:
|
81
85
|
Exclude:
|
@@ -83,10 +87,19 @@ Metrics/PerceivedComplexity:
|
|
83
87
|
- 'lib/lutaml/model/comparable_model.rb'
|
84
88
|
- 'lib/lutaml/model/serialize.rb'
|
85
89
|
- 'lib/lutaml/model/type/integer.rb'
|
90
|
+
- 'lib/lutaml/model/xml_adapter/builder/oga.rb'
|
91
|
+
- 'lib/lutaml/model/xml_adapter/builder/ox.rb'
|
86
92
|
- 'lib/lutaml/model/xml_adapter/nokogiri_adapter.rb'
|
93
|
+
- 'lib/lutaml/model/xml_adapter/oga_adapter.rb'
|
87
94
|
- 'lib/lutaml/model/xml_adapter/ox_adapter.rb'
|
88
95
|
- 'lib/lutaml/model/xml_adapter/xml_document.rb'
|
89
96
|
|
97
|
+
# Offense count: 1
|
98
|
+
# This cop supports unsafe autocorrection (--autocorrect-all).
|
99
|
+
Performance/MapCompact:
|
100
|
+
Exclude:
|
101
|
+
- 'lib/lutaml/model/serialize.rb'
|
102
|
+
|
90
103
|
# Offense count: 8
|
91
104
|
# Configuration parameters: Prefixes, AllowedPatterns.
|
92
105
|
# Prefixes: when, with, without
|
@@ -105,7 +118,7 @@ RSpec/DescribedClass:
|
|
105
118
|
Exclude:
|
106
119
|
- 'spec/lutaml/model/xml_mapping_spec.rb'
|
107
120
|
|
108
|
-
# Offense count:
|
121
|
+
# Offense count: 139
|
109
122
|
# Configuration parameters: CountAsOne.
|
110
123
|
RSpec/ExampleLength:
|
111
124
|
Max: 54
|
@@ -135,7 +148,7 @@ RSpec/MultipleDescribes:
|
|
135
148
|
- 'spec/lutaml/model/xml_adapter/xml_namespace_spec.rb'
|
136
149
|
- 'spec/lutaml/model/xml_adapter_spec.rb'
|
137
150
|
|
138
|
-
# Offense count:
|
151
|
+
# Offense count: 172
|
139
152
|
RSpec/MultipleExpectations:
|
140
153
|
Max: 14
|
141
154
|
|
@@ -144,23 +157,19 @@ RSpec/MultipleExpectations:
|
|
144
157
|
RSpec/MultipleMemoizedHelpers:
|
145
158
|
Max: 9
|
146
159
|
|
147
|
-
# Offense count:
|
160
|
+
# Offense count: 24
|
148
161
|
# Configuration parameters: AllowedGroups.
|
149
162
|
RSpec/NestedGroups:
|
150
163
|
Max: 4
|
151
164
|
|
152
|
-
# Offense count:
|
165
|
+
# Offense count: 9
|
153
166
|
RSpec/PendingWithoutReason:
|
154
167
|
Exclude:
|
155
|
-
- 'spec/lutaml/model/mixed_content_spec.rb'
|
156
168
|
- 'spec/lutaml/model/type/date_time_spec.rb'
|
157
169
|
- 'spec/lutaml/model/type/integer_spec.rb'
|
158
170
|
- 'spec/lutaml/model/type/time_spec.rb'
|
159
171
|
- 'spec/lutaml/model/type/time_without_date_spec.rb'
|
160
172
|
- 'spec/lutaml/model/validation_spec.rb'
|
161
|
-
- 'spec/lutaml/model/xml_adapter/oga_adapter_spec.rb'
|
162
|
-
- 'spec/lutaml/model/xml_adapter/xml_namespace_spec.rb'
|
163
|
-
- 'spec/lutaml/model/xml_adapter_spec.rb'
|
164
173
|
|
165
174
|
# Offense count: 1
|
166
175
|
RSpec/RemoveConst:
|
@@ -209,3 +218,10 @@ Style/MissingRespondToMissing:
|
|
209
218
|
Style/OptionalBooleanParameter:
|
210
219
|
Exclude:
|
211
220
|
- 'lib/lutaml/model/comparable_model.rb'
|
221
|
+
|
222
|
+
# Offense count: 1
|
223
|
+
# This cop supports unsafe autocorrection (--autocorrect-all).
|
224
|
+
# Configuration parameters: Mode.
|
225
|
+
Style/StringConcatenation:
|
226
|
+
Exclude:
|
227
|
+
- 'spec/lutaml/model/xml_mapping_spec.rb'
|
data/README.adoc
CHANGED
@@ -2131,6 +2131,121 @@ end
|
|
2131
2131
|
|
2132
2132
|
=== Advanced attribute mapping
|
2133
2133
|
|
2134
|
+
==== Multiple mappings to single attribute
|
2135
|
+
|
2136
|
+
The mapping methods support multiple names mapping to a single attribute using
|
2137
|
+
an array of names.
|
2138
|
+
|
2139
|
+
Syntax:
|
2140
|
+
|
2141
|
+
[source,ruby]
|
2142
|
+
----
|
2143
|
+
json | yaml | toml | key_value do
|
2144
|
+
map ["name1", "name2"], to: :attribute_name
|
2145
|
+
end
|
2146
|
+
|
2147
|
+
xml do
|
2148
|
+
map_element ["name1", "name2"], to: :attribute_name
|
2149
|
+
map_attribute ["attr1", "attr2"], to: :attribute_name
|
2150
|
+
end
|
2151
|
+
----
|
2152
|
+
|
2153
|
+
When serializing, the first element in the array of mapped names is always used
|
2154
|
+
as the output name.
|
2155
|
+
|
2156
|
+
|
2157
|
+
.Using multiple names to map to a single attribute
|
2158
|
+
[example]
|
2159
|
+
====
|
2160
|
+
[source,ruby]
|
2161
|
+
----
|
2162
|
+
class CustomModel < Lutaml::Model::Serializable
|
2163
|
+
attribute :full_name, Lutaml::Model::Type::String
|
2164
|
+
attribute :color, Lutaml::Model::Type::String
|
2165
|
+
attribute :id, Lutaml::Model::Type::String
|
2166
|
+
|
2167
|
+
json do
|
2168
|
+
map ["name", "custom_name"], with: { to: :name_to_json, from: :name_from_json }
|
2169
|
+
map ["color", "shade"], with: { to: :color_to_json, from: :color_from_json }
|
2170
|
+
end
|
2171
|
+
|
2172
|
+
xml do
|
2173
|
+
root "CustomModel"
|
2174
|
+
map_element ["name", "custom-name"], with: { to: :name_to_xml, from: :name_from_xml }
|
2175
|
+
map_element ["color", "shade"], with: { to: :color_to_xml, from: :color_from_xml }
|
2176
|
+
map_attribute ["id", "identifier"], to: :id
|
2177
|
+
end
|
2178
|
+
|
2179
|
+
# Custom methods for JSON
|
2180
|
+
def name_to_json(model, doc)
|
2181
|
+
doc["name"] = "JSON Model: #{model.full_name}"
|
2182
|
+
end
|
2183
|
+
|
2184
|
+
def name_from_json(model, value)
|
2185
|
+
model.full_name = value&.sub(/^JSON Model: /, "")
|
2186
|
+
end
|
2187
|
+
|
2188
|
+
def color_to_json(model, doc)
|
2189
|
+
doc["color"] = model.color.upcase
|
2190
|
+
end
|
2191
|
+
|
2192
|
+
def color_from_json(model, value)
|
2193
|
+
model.color = value&.downcase
|
2194
|
+
end
|
2195
|
+
|
2196
|
+
# Custom methods for XML
|
2197
|
+
def name_to_xml(model, parent, doc)
|
2198
|
+
el = doc.create_element("name")
|
2199
|
+
doc.add_text(el, "XML Model: #{model.full_name}")
|
2200
|
+
doc.add_element(parent, el)
|
2201
|
+
end
|
2202
|
+
|
2203
|
+
def name_from_xml(model, value)
|
2204
|
+
model.full_name = value.sub(/^XML Model: /, "")
|
2205
|
+
end
|
2206
|
+
|
2207
|
+
def color_to_xml(model, parent, doc)
|
2208
|
+
el = doc.create_element("color")
|
2209
|
+
doc.add_text(el, model.color.upcase)
|
2210
|
+
doc.add_element(parent, el)
|
2211
|
+
end
|
2212
|
+
|
2213
|
+
def color_from_xml(model, value)
|
2214
|
+
model.color = value.downcase
|
2215
|
+
end
|
2216
|
+
end
|
2217
|
+
----
|
2218
|
+
|
2219
|
+
For JSON:
|
2220
|
+
[source,json]
|
2221
|
+
----
|
2222
|
+
{
|
2223
|
+
"custom_name": "JSON Model: Vase",
|
2224
|
+
"shade": "BLUE",
|
2225
|
+
"identifier": "123"
|
2226
|
+
}
|
2227
|
+
----
|
2228
|
+
|
2229
|
+
For XML:
|
2230
|
+
[source,xml]
|
2231
|
+
----
|
2232
|
+
<CustomModel id="123">
|
2233
|
+
<name>XML Model: Vase</name>
|
2234
|
+
<color>BLUE</color>
|
2235
|
+
</CustomModel>
|
2236
|
+
----
|
2237
|
+
|
2238
|
+
[source,ruby]
|
2239
|
+
----
|
2240
|
+
> model = CustomModel.from_json(json)
|
2241
|
+
> model.full_name
|
2242
|
+
> # "Vase"
|
2243
|
+
> model.color
|
2244
|
+
> # "blue"
|
2245
|
+
----
|
2246
|
+
====
|
2247
|
+
|
2248
|
+
|
2134
2249
|
==== Attribute mapping delegation
|
2135
2250
|
|
2136
2251
|
Delegate attribute mappings to nested objects using the `delegate` option.
|
@@ -2641,6 +2756,13 @@ klin.validate
|
|
2641
2756
|
Lutaml::Model uses an adapter pattern to support multiple libraries for each
|
2642
2757
|
serialization format.
|
2643
2758
|
|
2759
|
+
Lutaml::Model supports the following serialization formats:
|
2760
|
+
|
2761
|
+
* XML (https://www.w3.org/TR/xmlschema-1/[W3C XML Schema (Second Edition)], XML 1.0)
|
2762
|
+
* YAML (https://yaml.org/[YAML version 1.2])
|
2763
|
+
* JSON (https://www.ecma-international.org/publications-and-standards/standards/ecma-404/[ECMA-404 The JSON Data Interchange Standard], unofficial link: https://www.json.org[JSON])
|
2764
|
+
* TOML (https://toml.io/en[TOML version 1.0])
|
2765
|
+
|
2644
2766
|
You will need to specify the configuration for the adapter you want to use. The
|
2645
2767
|
easiest way is to copy and paste the following configuration into your code.
|
2646
2768
|
|
@@ -2684,9 +2806,25 @@ NOTE: By default `yaml_adapter_type` and `json_adapter_type` are set to
|
|
2684
2806
|
|
2685
2807
|
Lutaml::Model supports the following XML adapters:
|
2686
2808
|
|
2687
|
-
|
2688
|
-
|
2689
|
-
|
2809
|
+
Nokogiri::
|
2810
|
+
(default)
|
2811
|
+
Popular `libxml` based XML parser for Ruby.
|
2812
|
+
Requires native extensions (i.e. compiled C code).
|
2813
|
+
Requires the `nokogiri` gem.
|
2814
|
+
|
2815
|
+
Oga::
|
2816
|
+
(optional)
|
2817
|
+
Pure Ruby XML parser.
|
2818
|
+
Does not require native extensions and is suitable for
|
2819
|
+
https://opalrb.com[Opal] (Ruby on JavaScript).
|
2820
|
+
Requires the `oga` gem.
|
2821
|
+
|
2822
|
+
Ox::
|
2823
|
+
(optional)
|
2824
|
+
Fast XML parser and object serializer for Ruby, implemented partially in C.
|
2825
|
+
Requires native extensions (i.e. compiled C code).
|
2826
|
+
Requires the `ox` gem.
|
2827
|
+
|
2690
2828
|
|
2691
2829
|
.Using the Nokogiri XML adapter
|
2692
2830
|
[source,ruby]
|
@@ -2726,7 +2864,10 @@ end
|
|
2726
2864
|
|
2727
2865
|
Lutaml::Model supports only one YAML adapter.
|
2728
2866
|
|
2729
|
-
|
2867
|
+
YAML::
|
2868
|
+
(default)
|
2869
|
+
The Psych YAML parser and emitter for Ruby.
|
2870
|
+
Included in the Ruby standard library.
|
2730
2871
|
|
2731
2872
|
.Using the YAML adapter
|
2732
2873
|
[source,ruby]
|
@@ -2745,8 +2886,15 @@ end
|
|
2745
2886
|
|
2746
2887
|
Lutaml::Model supports the following JSON adapters:
|
2747
2888
|
|
2748
|
-
|
2749
|
-
|
2889
|
+
JSON::
|
2890
|
+
(default)
|
2891
|
+
The standard JSON library for Ruby.
|
2892
|
+
Included in the Ruby standard library.
|
2893
|
+
|
2894
|
+
MultiJson::
|
2895
|
+
(optional)
|
2896
|
+
A gem that provides a common interface to multiple JSON libraries.
|
2897
|
+
Requires the `multi_json` gem.
|
2750
2898
|
|
2751
2899
|
.Using the JSON adapter
|
2752
2900
|
[source,ruby]
|
@@ -2774,8 +2922,18 @@ end
|
|
2774
2922
|
|
2775
2923
|
Lutaml::Model supports the following TOML adapters:
|
2776
2924
|
|
2777
|
-
|
2778
|
-
|
2925
|
+
Toml-rb::
|
2926
|
+
(default)
|
2927
|
+
A TOML parser and serializer for Ruby that is compatible with the TOML v1.0.0
|
2928
|
+
specification.
|
2929
|
+
Requires the `toml-rb` gem.
|
2930
|
+
|
2931
|
+
Tomlib::
|
2932
|
+
(optional)
|
2933
|
+
Toml-rb fork that is compatible with the TOML v1.0.0 specification, but with
|
2934
|
+
additional features.
|
2935
|
+
Requires the `tomlib` gem.
|
2936
|
+
|
2779
2937
|
|
2780
2938
|
.Using the Toml-rb adapter
|
2781
2939
|
[source,ruby]
|
@@ -12,7 +12,8 @@ module Lutaml
|
|
12
12
|
render_default: false,
|
13
13
|
with: {},
|
14
14
|
delegate: nil,
|
15
|
-
child_mappings: nil
|
15
|
+
child_mappings: nil,
|
16
|
+
id: nil
|
16
17
|
)
|
17
18
|
super(
|
18
19
|
name,
|
@@ -21,6 +22,7 @@ module Lutaml
|
|
21
22
|
render_default: render_default,
|
22
23
|
with: with,
|
23
24
|
delegate: delegate,
|
25
|
+
id: id
|
24
26
|
)
|
25
27
|
|
26
28
|
@child_mappings = child_mappings
|
@@ -16,7 +16,8 @@ module Lutaml
|
|
16
16
|
render_default: false,
|
17
17
|
with: {},
|
18
18
|
attribute: false,
|
19
|
-
delegate: nil
|
19
|
+
delegate: nil,
|
20
|
+
id: nil
|
20
21
|
)
|
21
22
|
@name = name
|
22
23
|
@to = to
|
@@ -25,6 +26,7 @@ module Lutaml
|
|
25
26
|
@custom_methods = with
|
26
27
|
@attribute = attribute
|
27
28
|
@delegate = delegate
|
29
|
+
@id = id
|
28
30
|
end
|
29
31
|
|
30
32
|
alias from name
|
@@ -42,6 +44,8 @@ module Lutaml
|
|
42
44
|
if delegate
|
43
45
|
model.public_send(delegate).public_send(to)
|
44
46
|
else
|
47
|
+
return if to.nil?
|
48
|
+
|
45
49
|
model.public_send(to)
|
46
50
|
end
|
47
51
|
end
|
@@ -56,7 +60,7 @@ module Lutaml
|
|
56
60
|
|
57
61
|
def deserialize(model, value, attributes, mapper_class = nil)
|
58
62
|
if custom_methods[:from]
|
59
|
-
mapper_class.new.send(custom_methods[:from], model, value)
|
63
|
+
mapper_class.new.send(custom_methods[:from], model, value) unless value.nil?
|
60
64
|
elsif delegate
|
61
65
|
if model.public_send(delegate).nil?
|
62
66
|
model.public_send(:"#{delegate}=", attributes[delegate].type.new)
|
@@ -68,6 +72,14 @@ module Lutaml
|
|
68
72
|
end
|
69
73
|
end
|
70
74
|
|
75
|
+
def using_custom_methods?
|
76
|
+
!custom_methods.empty?
|
77
|
+
end
|
78
|
+
|
79
|
+
def multiple_mappings?
|
80
|
+
name.is_a?(Array)
|
81
|
+
end
|
82
|
+
|
71
83
|
def deep_dup
|
72
84
|
raise NotImplementedError, "Subclasses must implement `deep_dup`."
|
73
85
|
end
|
@@ -21,6 +21,7 @@ module Lutaml
|
|
21
21
|
|
22
22
|
def self.included(base)
|
23
23
|
base.extend(ClassMethods)
|
24
|
+
base.initialize_attrs(base)
|
24
25
|
end
|
25
26
|
|
26
27
|
module ClassMethods
|
@@ -28,14 +29,18 @@ module Lutaml
|
|
28
29
|
|
29
30
|
def inherited(subclass)
|
30
31
|
super
|
32
|
+
subclass.initialize_attrs(self)
|
33
|
+
end
|
31
34
|
|
32
|
-
|
33
|
-
|
35
|
+
def included(base)
|
36
|
+
base.extend(ClassMethods)
|
37
|
+
base.initialize_attrs(self)
|
38
|
+
end
|
34
39
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
40
|
+
def initialize_attrs(source_class)
|
41
|
+
@mappings = Utils.deep_dup(source_class.instance_variable_get(:@mappings)) || {}
|
42
|
+
@attributes = Utils.deep_dup(source_class.instance_variable_get(:@attributes)) || {}
|
43
|
+
instance_variable_set(:@model, self)
|
39
44
|
end
|
40
45
|
|
41
46
|
def model(klass = nil)
|
@@ -264,15 +269,18 @@ module Lutaml
|
|
264
269
|
|
265
270
|
value = instance.send(name)
|
266
271
|
|
267
|
-
next if Utils.blank?(value) && !rule.render_nil
|
268
|
-
|
269
272
|
attribute = attributes[name]
|
270
273
|
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
274
|
+
value = if rule.child_mappings
|
275
|
+
generate_hash_from_child_mappings(value, rule.child_mappings)
|
276
|
+
else
|
277
|
+
attribute.serialize(value, format, options)
|
278
|
+
end
|
279
|
+
|
280
|
+
next if Utils.blank?(value) && !rule.render_nil
|
281
|
+
|
282
|
+
rule_from_name = rule.multiple_mappings? ? rule.from.first.to_s : rule.from.to_s
|
283
|
+
hash[rule_from_name] = value
|
276
284
|
end
|
277
285
|
end
|
278
286
|
|
@@ -282,39 +290,14 @@ module Lutaml
|
|
282
290
|
return if value.nil? && !rule.render_nil
|
283
291
|
|
284
292
|
attribute = instance.send(rule.delegate).class.attributes[name]
|
285
|
-
|
293
|
+
rule_from_name = rule.multiple_mappings? ? rule.from.first.to_s : rule.from.to_s
|
294
|
+
hash[rule_from_name] = attribute.serialize(value, format)
|
286
295
|
end
|
287
296
|
|
288
297
|
def mappings_for(format)
|
289
298
|
mappings[format] || default_mappings(format)
|
290
299
|
end
|
291
300
|
|
292
|
-
def attr_value(attrs, name, attr_rule)
|
293
|
-
value = if attrs.key?(name.to_sym)
|
294
|
-
attrs[name.to_sym]
|
295
|
-
elsif attrs.key?(name.to_s)
|
296
|
-
attrs[name.to_s]
|
297
|
-
else
|
298
|
-
attr_rule.default
|
299
|
-
end
|
300
|
-
|
301
|
-
if attr_rule.collection? || value.is_a?(Array)
|
302
|
-
(value || []).map do |v|
|
303
|
-
if v.is_a?(Hash)
|
304
|
-
attr_rule.type.new(v)
|
305
|
-
else
|
306
|
-
# TODO: This code is problematic because Type.cast does not know
|
307
|
-
# about all the types.
|
308
|
-
Lutaml::Model::Type.cast(v, attr_rule.type)
|
309
|
-
end
|
310
|
-
end
|
311
|
-
else
|
312
|
-
# TODO: This code is problematic because Type.cast does not know
|
313
|
-
# about all the types.
|
314
|
-
Lutaml::Model::Type.cast(value, attr_rule.type)
|
315
|
-
end
|
316
|
-
end
|
317
|
-
|
318
301
|
def default_mappings(format)
|
319
302
|
klass = format == :xml ? XmlMapping : KeyValueMapping
|
320
303
|
|
@@ -413,8 +396,7 @@ module Lutaml
|
|
413
396
|
mappings = mappings_for(:xml).mappings
|
414
397
|
|
415
398
|
if doc.is_a?(Array)
|
416
|
-
raise "May be `collection: true` is"
|
417
|
-
"missing for #{self} in #{options[:caller_class]}"
|
399
|
+
raise "May be `collection: true` is missing for #{self} in #{options[:caller_class]}"
|
418
400
|
end
|
419
401
|
|
420
402
|
if instance.respond_to?(:ordered=) && doc.is_a?(Lutaml::Model::MappingHash)
|
@@ -438,17 +420,18 @@ module Lutaml
|
|
438
420
|
|
439
421
|
attr = attribute_for_rule(rule)
|
440
422
|
|
423
|
+
namespaced_names = rule.namespaced_names(options[:default_namespace])
|
424
|
+
|
441
425
|
value = if rule.raw_mapping?
|
442
426
|
doc.node.inner_xml
|
443
427
|
elsif rule.content_mapping?
|
444
428
|
doc[rule.content_key]
|
445
|
-
elsif doc.
|
446
|
-
doc
|
429
|
+
elsif key = (namespaced_names & doc.keys).first
|
430
|
+
doc[key]
|
447
431
|
else
|
448
432
|
defaults_used << rule.to
|
449
433
|
attr&.default || rule.to_value_for(instance)
|
450
434
|
end
|
451
|
-
|
452
435
|
value = normalize_xml_value(value, rule, attr, options)
|
453
436
|
rule.deserialize(instance, value, attributes, self)
|
454
437
|
end
|
@@ -467,13 +450,19 @@ module Lutaml
|
|
467
450
|
|
468
451
|
attr = attribute_for_rule(rule)
|
469
452
|
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
453
|
+
names = rule.multiple_mappings? ? rule.name : [rule.name]
|
454
|
+
|
455
|
+
value = names.collect do |rule_name|
|
456
|
+
if doc.key?(rule_name.to_s)
|
457
|
+
doc[rule_name.to_s]
|
458
|
+
elsif doc.key?(rule_name.to_sym)
|
459
|
+
doc[rule_name.to_sym]
|
460
|
+
else
|
461
|
+
attr&.default
|
462
|
+
end
|
463
|
+
end.compact.first
|
475
464
|
|
476
|
-
if rule.
|
465
|
+
if rule.using_custom_methods?
|
477
466
|
if Utils.present?(value)
|
478
467
|
value = new.send(rule.custom_methods[:from], instance, value)
|
479
468
|
end
|
@@ -567,7 +556,7 @@ module Lutaml
|
|
567
556
|
|
568
557
|
self.class.attributes.each do |name, attr|
|
569
558
|
value = if attrs.key?(name) || attrs.key?(name.to_s)
|
570
|
-
|
559
|
+
attr_value(attrs, name, attr)
|
571
560
|
else
|
572
561
|
using_default_for(name)
|
573
562
|
attr.default
|
@@ -584,6 +573,32 @@ module Lutaml
|
|
584
573
|
end
|
585
574
|
end
|
586
575
|
|
576
|
+
def attr_value(attrs, name, attr_rule)
|
577
|
+
value = if attrs.key?(name.to_sym)
|
578
|
+
attrs[name.to_sym]
|
579
|
+
elsif attrs.key?(name.to_s)
|
580
|
+
attrs[name.to_s]
|
581
|
+
else
|
582
|
+
attr_rule.default
|
583
|
+
end
|
584
|
+
|
585
|
+
if attr_rule.collection? || value.is_a?(Array)
|
586
|
+
(value || []).map do |v|
|
587
|
+
if v.is_a?(Hash)
|
588
|
+
attr_rule.type.new(v)
|
589
|
+
else
|
590
|
+
# TODO: This code is problematic because Type.cast does not know
|
591
|
+
# about all the types.
|
592
|
+
Lutaml::Model::Type.cast(v, attr_rule.type)
|
593
|
+
end
|
594
|
+
end
|
595
|
+
else
|
596
|
+
# TODO: This code is problematic because Type.cast does not know
|
597
|
+
# about all the types.
|
598
|
+
Lutaml::Model::Type.cast(value, attr_rule.type)
|
599
|
+
end
|
600
|
+
end
|
601
|
+
|
587
602
|
def using_default_for(attribute_name)
|
588
603
|
@using_default[attribute_name] = true
|
589
604
|
end
|
data/lib/lutaml/model/version.rb
CHANGED