lutaml-model 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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