lutaml-model 0.3.0 → 0.3.2
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.yml +0 -5
- data/.rubocop_todo.yml +20 -101
- data/Gemfile +3 -18
- data/README.adoc +1100 -140
- data/lib/lutaml/model/attribute.rb +15 -2
- data/lib/lutaml/model/config.rb +0 -1
- data/lib/lutaml/model/error/invalid_value_error.rb +18 -0
- data/lib/lutaml/model/error.rb +8 -0
- data/lib/lutaml/model/json_adapter/json_document.rb +20 -0
- data/lib/lutaml/model/json_adapter/json_object.rb +28 -0
- data/lib/lutaml/model/json_adapter/{multi_json.rb → multi_json_adapter.rb} +2 -3
- data/lib/lutaml/model/json_adapter/{standard.rb → standard_json_adapter.rb} +2 -3
- data/lib/lutaml/model/json_adapter.rb +1 -31
- data/lib/lutaml/model/key_value_mapping.rb +9 -2
- data/lib/lutaml/model/key_value_mapping_rule.rb +0 -1
- data/lib/lutaml/model/mapping_hash.rb +0 -2
- data/lib/lutaml/model/mapping_rule.rb +5 -3
- data/lib/lutaml/model/schema/json_schema.rb +0 -1
- data/lib/lutaml/model/schema/relaxng_schema.rb +0 -1
- data/lib/lutaml/model/schema/xsd_schema.rb +0 -1
- data/lib/lutaml/model/schema/yaml_schema.rb +0 -1
- data/lib/lutaml/model/schema.rb +0 -1
- data/lib/lutaml/model/serializable.rb +0 -1
- data/lib/lutaml/model/serialize.rb +241 -153
- data/lib/lutaml/model/toml_adapter/toml_document.rb +20 -0
- data/lib/lutaml/model/toml_adapter/toml_object.rb +28 -0
- data/lib/lutaml/model/toml_adapter/toml_rb_adapter.rb +4 -5
- data/lib/lutaml/model/toml_adapter/tomlib_adapter.rb +2 -3
- data/lib/lutaml/model/toml_adapter.rb +0 -31
- data/lib/lutaml/model/type/date_time.rb +20 -0
- data/lib/lutaml/model/type/json.rb +34 -0
- data/lib/lutaml/model/type/time_without_date.rb +4 -3
- data/lib/lutaml/model/type.rb +61 -124
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/model/xml_adapter/nokogiri_adapter.rb +20 -13
- data/lib/lutaml/model/xml_adapter/oga_adapter.rb +4 -5
- data/lib/lutaml/model/xml_adapter/ox_adapter.rb +24 -17
- data/lib/lutaml/model/xml_adapter/xml_attribute.rb +27 -0
- data/lib/lutaml/model/xml_adapter/xml_document.rb +184 -0
- data/lib/lutaml/model/xml_adapter/xml_element.rb +94 -0
- data/lib/lutaml/model/xml_adapter/xml_namespace.rb +49 -0
- data/lib/lutaml/model/xml_adapter.rb +0 -266
- data/lib/lutaml/model/xml_mapping.rb +1 -1
- data/lib/lutaml/model/xml_mapping_rule.rb +3 -4
- data/lib/lutaml/model/yaml_adapter/standard_yaml_adapter.rb +34 -0
- data/lib/lutaml/model/yaml_adapter/yaml_document.rb +20 -0
- data/lib/lutaml/model/yaml_adapter/yaml_object.rb +28 -0
- data/lib/lutaml/model/yaml_adapter.rb +1 -19
- data/lib/lutaml/model.rb +7 -5
- metadata +19 -5
- data/lib/lutaml/model/xml_namespace.rb +0 -47
@@ -1,4 +1,3 @@
|
|
1
|
-
# lib/lutaml/model/serialize.rb
|
2
1
|
require_relative "yaml_adapter"
|
3
2
|
require_relative "xml_adapter"
|
4
3
|
require_relative "config"
|
@@ -25,11 +24,24 @@ module Lutaml
|
|
25
24
|
def inherited(subclass)
|
26
25
|
super
|
27
26
|
|
27
|
+
@mappings ||= {}
|
28
|
+
@attributes ||= {}
|
29
|
+
|
28
30
|
subclass.instance_variable_set(:@attributes, @attributes.dup)
|
31
|
+
subclass.instance_variable_set(:@mappings, @mappings.dup)
|
32
|
+
subclass.instance_variable_set(:@model, subclass)
|
29
33
|
end
|
30
34
|
|
35
|
+
def model(klass = nil)
|
36
|
+
if klass
|
37
|
+
@model = klass
|
38
|
+
else
|
39
|
+
@model
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Define an attribute for the model
|
31
44
|
def attribute(name, type, options = {})
|
32
|
-
self.attributes ||= {}
|
33
45
|
attr = Attribute.new(name, type, options)
|
34
46
|
attributes[name] = attr
|
35
47
|
|
@@ -38,19 +50,33 @@ module Lutaml
|
|
38
50
|
end
|
39
51
|
|
40
52
|
define_method(:"#{name}=") do |value|
|
53
|
+
unless self.class.attr_value_valid?(name, value)
|
54
|
+
raise Lutaml::Model::InvalidValueError.new(name, value, options[:values])
|
55
|
+
end
|
56
|
+
|
41
57
|
instance_variable_set(:"@#{name}", value)
|
42
58
|
end
|
43
59
|
end
|
44
60
|
|
61
|
+
# Check if the value to be assigned is valid for the attribute
|
62
|
+
def attr_value_valid?(name, value)
|
63
|
+
attr = attributes[name]
|
64
|
+
|
65
|
+
return true unless attr.options[:values]
|
66
|
+
|
67
|
+
# If value validation failed but there is a default value, do not
|
68
|
+
# raise a validation error
|
69
|
+
attr.options[:values].include?(value || attr.default)
|
70
|
+
end
|
71
|
+
|
45
72
|
FORMATS.each do |format|
|
46
73
|
define_method(format) do |&block|
|
47
|
-
self.mappings ||= {}
|
48
74
|
klass = format == :xml ? XmlMapping : KeyValueMapping
|
49
|
-
|
50
|
-
|
75
|
+
mappings[format] = klass.new
|
76
|
+
mappings[format].instance_eval(&block)
|
51
77
|
|
52
|
-
if format == :xml && !
|
53
|
-
|
78
|
+
if format == :xml && !mappings[format].root_element
|
79
|
+
mappings[format].root(model.to_s)
|
54
80
|
end
|
55
81
|
end
|
56
82
|
|
@@ -59,24 +85,200 @@ module Lutaml
|
|
59
85
|
doc = adapter.parse(data)
|
60
86
|
mapped_attrs = apply_mappings(doc.to_h, format)
|
61
87
|
# apply_content_mapping(doc, mapped_attrs) if format == :xml
|
62
|
-
|
88
|
+
generate_model_object(self, mapped_attrs)
|
89
|
+
end
|
90
|
+
|
91
|
+
define_method(:"to_#{format}") do |instance|
|
92
|
+
unless instance.is_a?(model)
|
93
|
+
msg = "argument is a '#{instance.class}' but should be a '#{model}'"
|
94
|
+
raise Lutaml::Model::IncorrectModelError, msg
|
95
|
+
end
|
96
|
+
|
97
|
+
adapter = Lutaml::Model::Config.public_send(:"#{format}_adapter")
|
98
|
+
|
99
|
+
if format == :xml
|
100
|
+
xml_options = { mapper_class: self }
|
101
|
+
|
102
|
+
adapter.new(instance).public_send(:"to_#{format}", xml_options)
|
103
|
+
else
|
104
|
+
hash = hash_representation(instance, format)
|
105
|
+
adapter.new(hash).public_send(:"to_#{format}")
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def hash_representation(instance, format, options = {})
|
111
|
+
only = options[:only]
|
112
|
+
except = options[:except]
|
113
|
+
mappings = mappings_for(format).mappings
|
114
|
+
|
115
|
+
mappings.each_with_object({}) do |rule, hash|
|
116
|
+
name = rule.to
|
117
|
+
next if except&.include?(name) || (only && !only.include?(name))
|
118
|
+
|
119
|
+
next handle_delegate(instance, rule, hash) if rule.delegate
|
120
|
+
|
121
|
+
value = if rule.custom_methods[:to]
|
122
|
+
instance.send(rule.custom_methods[:to], instance, instance.send(name))
|
123
|
+
else
|
124
|
+
instance.send(name)
|
125
|
+
end
|
126
|
+
|
127
|
+
next if value.nil? && !rule.render_nil
|
128
|
+
|
129
|
+
attribute = attributes[name]
|
130
|
+
|
131
|
+
hash[rule.from] = if rule.child_mappings
|
132
|
+
generate_hash_from_child_mappings(value, rule.child_mappings)
|
133
|
+
elsif value.is_a?(Array)
|
134
|
+
value.map do |v|
|
135
|
+
if attribute.type <= Serialize
|
136
|
+
attribute.type.hash_representation(v, format, options)
|
137
|
+
else
|
138
|
+
attribute.type.serialize(v)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
elsif attribute.type <= Serialize
|
142
|
+
attribute.type.hash_representation(value, format, options)
|
143
|
+
else
|
144
|
+
attribute.type.serialize(value)
|
145
|
+
end
|
63
146
|
end
|
64
147
|
end
|
65
148
|
|
149
|
+
def handle_delegate(instance, rule, hash)
|
150
|
+
name = rule.to
|
151
|
+
value = instance.send(rule.delegate).send(name)
|
152
|
+
return if value.nil? && !rule.render_nil
|
153
|
+
|
154
|
+
attribute = instance.send(rule.delegate).class.attributes[name]
|
155
|
+
hash[rule.from] = case value
|
156
|
+
when Array
|
157
|
+
value.map do |v|
|
158
|
+
if v.is_a?(Serialize)
|
159
|
+
hash_representation(v, format, options)
|
160
|
+
else
|
161
|
+
attribute.type.serialize(v)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
else
|
165
|
+
if value.is_a?(Serialize)
|
166
|
+
hash_representation(value, format, options)
|
167
|
+
else
|
168
|
+
attribute.type.serialize(value)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
66
173
|
def mappings_for(format)
|
67
|
-
|
174
|
+
mappings[format] || default_mappings(format)
|
175
|
+
end
|
176
|
+
|
177
|
+
def generate_model_object(type, mapped_attrs)
|
178
|
+
return type.model.new(mapped_attrs) if self == model
|
179
|
+
|
180
|
+
instance = type.model.new
|
181
|
+
|
182
|
+
type.attributes.each do |name, attr|
|
183
|
+
value = attr_value(mapped_attrs, name, attr)
|
184
|
+
|
185
|
+
instance.send(:"#{name}=", ensure_utf8(value))
|
186
|
+
end
|
187
|
+
|
188
|
+
instance
|
189
|
+
end
|
190
|
+
|
191
|
+
def attr_value(attrs, name, attr_rule)
|
192
|
+
value = if attrs.key?(name)
|
193
|
+
attrs[name]
|
194
|
+
elsif attrs.key?(name.to_sym)
|
195
|
+
attrs[name.to_sym]
|
196
|
+
elsif attrs.key?(name.to_s)
|
197
|
+
attrs[name.to_s]
|
198
|
+
else
|
199
|
+
attr_rule.default
|
200
|
+
end
|
201
|
+
|
202
|
+
if attr_rule.collection? || value.is_a?(Array)
|
203
|
+
(value || []).map do |v|
|
204
|
+
if v.is_a?(Hash)
|
205
|
+
attr_rule.type.new(v)
|
206
|
+
else
|
207
|
+
# TODO: This code is problematic because Type.cast does not know
|
208
|
+
# about all the types.
|
209
|
+
Lutaml::Model::Type.cast(
|
210
|
+
v, attr_rule.type
|
211
|
+
)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
elsif value.is_a?(Hash) && attr_rule.type != Lutaml::Model::Type::Hash
|
215
|
+
generate_model_object(attr_rule.type, value)
|
216
|
+
else
|
217
|
+
# TODO: This code is problematic because Type.cast does not know
|
218
|
+
# about all the types.
|
219
|
+
Lutaml::Model::Type.cast(value, attr_rule.type)
|
220
|
+
end
|
68
221
|
end
|
69
222
|
|
70
223
|
def default_mappings(format)
|
71
224
|
klass = format == :xml ? XmlMapping : KeyValueMapping
|
72
225
|
klass.new.tap do |mapping|
|
73
226
|
attributes&.each do |name, attr|
|
74
|
-
mapping.map_element(
|
75
|
-
|
227
|
+
mapping.map_element(
|
228
|
+
name.to_s,
|
229
|
+
to: name,
|
230
|
+
render_nil: attr.render_nil?,
|
231
|
+
)
|
76
232
|
end
|
77
233
|
end
|
78
234
|
end
|
79
235
|
|
236
|
+
def apply_child_mappings(hash, child_mappings)
|
237
|
+
return hash unless child_mappings
|
238
|
+
|
239
|
+
hash.map do |key, value|
|
240
|
+
child_mappings.to_h do |attr_name, path|
|
241
|
+
attr_value = if path == :key
|
242
|
+
key
|
243
|
+
elsif path == :value
|
244
|
+
value
|
245
|
+
else
|
246
|
+
path = [path] unless path.is_a?(Array)
|
247
|
+
value.dig(*path.map(&:to_s))
|
248
|
+
end
|
249
|
+
|
250
|
+
[attr_name, attr_value]
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
def generate_hash_from_child_mappings(value, child_mappings)
|
256
|
+
return value unless child_mappings
|
257
|
+
|
258
|
+
hash = {}
|
259
|
+
|
260
|
+
value.each do |child_obj|
|
261
|
+
map_key = nil
|
262
|
+
map_value = {}
|
263
|
+
child_mappings.each do |attr_name, path|
|
264
|
+
if path == :key
|
265
|
+
map_key = child_obj.send(attr_name)
|
266
|
+
elsif path == :value
|
267
|
+
map_value = child_obj.send(attr_name)
|
268
|
+
else
|
269
|
+
path = [path] unless path.is_a?(Array)
|
270
|
+
path[0...-1].inject(map_value) do |acc, k|
|
271
|
+
acc[k.to_s] ||= {}
|
272
|
+
end.public_send(:[]=, path.last.to_s, child_obj.send(attr_name))
|
273
|
+
end
|
274
|
+
end
|
275
|
+
# hash[mapping.name] ||= {}
|
276
|
+
hash[map_key] = map_value
|
277
|
+
end
|
278
|
+
|
279
|
+
hash
|
280
|
+
end
|
281
|
+
|
80
282
|
def apply_mappings(doc, format)
|
81
283
|
return apply_xml_mapping(doc) if format == :xml
|
82
284
|
|
@@ -98,6 +300,8 @@ module Lutaml
|
|
98
300
|
attr.default
|
99
301
|
end
|
100
302
|
|
303
|
+
value = apply_child_mappings(value, rule.child_mappings)
|
304
|
+
|
101
305
|
if attr.collection?
|
102
306
|
value = (value || []).map do |v|
|
103
307
|
attr.type <= Serialize ? attr.type.apply_mappings(v, format) : v
|
@@ -167,6 +371,21 @@ module Lutaml
|
|
167
371
|
hash[rule.to] = value
|
168
372
|
end
|
169
373
|
end
|
374
|
+
|
375
|
+
def ensure_utf8(value)
|
376
|
+
case value
|
377
|
+
when String
|
378
|
+
value.encode("UTF-8", invalid: :replace, undef: :replace, replace: "")
|
379
|
+
when Array
|
380
|
+
value.map { |v| ensure_utf8(v) }
|
381
|
+
when Hash
|
382
|
+
value.transform_keys do |k|
|
383
|
+
ensure_utf8(k)
|
384
|
+
end.transform_values { |v| ensure_utf8(v) }
|
385
|
+
else
|
386
|
+
value
|
387
|
+
end
|
388
|
+
end
|
170
389
|
end
|
171
390
|
|
172
391
|
attr_reader :element_order
|
@@ -180,37 +399,9 @@ module Lutaml
|
|
180
399
|
end
|
181
400
|
|
182
401
|
self.class.attributes.each do |name, attr|
|
183
|
-
value = attr_value(attrs, name, attr)
|
184
|
-
|
185
|
-
send(:"#{name}=", ensure_utf8(value))
|
186
|
-
end
|
187
|
-
end
|
402
|
+
value = self.class.attr_value(attrs, name, attr)
|
188
403
|
|
189
|
-
|
190
|
-
value = if attrs.key?(name)
|
191
|
-
attrs[name]
|
192
|
-
elsif attrs.key?(name.to_sym)
|
193
|
-
attrs[name.to_sym]
|
194
|
-
elsif attrs.key?(name.to_s)
|
195
|
-
attrs[name.to_s]
|
196
|
-
else
|
197
|
-
attr_rule.default
|
198
|
-
end
|
199
|
-
|
200
|
-
if attr_rule.collection? || value.is_a?(Array)
|
201
|
-
(value || []).map do |v|
|
202
|
-
if v.is_a?(Hash)
|
203
|
-
attr_rule.type.new(v)
|
204
|
-
else
|
205
|
-
Lutaml::Model::Type.cast(
|
206
|
-
v, attr_rule.type
|
207
|
-
)
|
208
|
-
end
|
209
|
-
end
|
210
|
-
elsif value.is_a?(Hash) && attr_rule.type != Lutaml::Model::Type::Hash
|
211
|
-
attr_rule.type.new(value)
|
212
|
-
else
|
213
|
-
Lutaml::Model::Type.cast(value, attr_rule.type)
|
404
|
+
send(:"#{name}=", self.class.ensure_utf8(value))
|
214
405
|
end
|
215
406
|
end
|
216
407
|
|
@@ -226,119 +417,16 @@ module Lutaml
|
|
226
417
|
hash[key] || hash[key.to_sym] || hash[key.to_s]
|
227
418
|
end
|
228
419
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
# end
|
238
|
-
# adapter.new(representation).send("to_#{format}", options)
|
239
|
-
# end
|
240
|
-
# end
|
241
|
-
|
242
|
-
def to_xml(options = {})
|
243
|
-
adapter = Lutaml::Model::Config.xml_adapter
|
244
|
-
adapter.new(self).to_xml(options)
|
245
|
-
end
|
246
|
-
|
247
|
-
def to_json(options = {})
|
248
|
-
adapter = Lutaml::Model::Config.json_adapter
|
249
|
-
adapter.new(hash_representation(:json, options)).to_json(options)
|
250
|
-
end
|
251
|
-
|
252
|
-
def to_yaml(options = {})
|
253
|
-
adapter = Lutaml::Model::Config.yaml_adapter
|
254
|
-
adapter.to_yaml(self, options)
|
255
|
-
end
|
256
|
-
|
257
|
-
def to_toml(options = {})
|
258
|
-
adapter = Lutaml::Model::Config.toml_adapter
|
259
|
-
adapter.new(hash_representation(:toml, options)).to_toml
|
260
|
-
end
|
261
|
-
|
262
|
-
# TODO: END Make this work
|
263
|
-
|
264
|
-
def hash_representation(format, options = {})
|
265
|
-
only = options[:only]
|
266
|
-
except = options[:except]
|
267
|
-
mappings = self.class.mappings_for(format).mappings
|
268
|
-
|
269
|
-
mappings.each_with_object({}) do |rule, hash|
|
270
|
-
name = rule.to
|
271
|
-
next if except&.include?(name) || (only && !only.include?(name))
|
272
|
-
|
273
|
-
next handle_delegate(self, rule, hash) if rule.delegate
|
274
|
-
|
275
|
-
value = if rule.custom_methods[:to]
|
276
|
-
send(rule.custom_methods[:to], self, send(name))
|
277
|
-
else
|
278
|
-
send(name)
|
279
|
-
end
|
280
|
-
|
281
|
-
next if value.nil? && !rule.render_nil
|
282
|
-
|
283
|
-
attribute = self.class.attributes[name]
|
284
|
-
|
285
|
-
hash[rule.from] = case value
|
286
|
-
when Array
|
287
|
-
value.map do |v|
|
288
|
-
if v.is_a?(Serialize)
|
289
|
-
v.hash_representation(format, options)
|
290
|
-
else
|
291
|
-
attribute.type.serialize(v)
|
292
|
-
end
|
293
|
-
end
|
294
|
-
else
|
295
|
-
if value.is_a?(Serialize)
|
296
|
-
value.hash_representation(format, options)
|
297
|
-
else
|
298
|
-
attribute.type.serialize(value)
|
299
|
-
end
|
300
|
-
end
|
301
|
-
end
|
302
|
-
end
|
303
|
-
|
304
|
-
private
|
305
|
-
|
306
|
-
def handle_delegate(_obj, rule, hash)
|
307
|
-
name = rule.to
|
308
|
-
value = send(rule.delegate).send(name)
|
309
|
-
return if value.nil? && !rule.render_nil
|
310
|
-
|
311
|
-
attribute = send(rule.delegate).class.attributes[name]
|
312
|
-
hash[rule.from] = case value
|
313
|
-
when Array
|
314
|
-
value.map do |v|
|
315
|
-
if v.is_a?(Serialize)
|
316
|
-
v.hash_representation(format, options)
|
317
|
-
else
|
318
|
-
attribute.type.serialize(v)
|
319
|
-
end
|
320
|
-
end
|
321
|
-
else
|
322
|
-
if value.is_a?(Serialize)
|
323
|
-
value.hash_representation(format, options)
|
324
|
-
else
|
325
|
-
attribute.type.serialize(value)
|
326
|
-
end
|
327
|
-
end
|
328
|
-
end
|
420
|
+
FORMATS.each do |format|
|
421
|
+
define_method(:"to_#{format}") do |options = {}|
|
422
|
+
adapter = Lutaml::Model::Config.public_send(:"#{format}_adapter")
|
423
|
+
representation = if format == :xml
|
424
|
+
self
|
425
|
+
else
|
426
|
+
self.class.hash_representation(self, format, options)
|
427
|
+
end
|
329
428
|
|
330
|
-
|
331
|
-
case value
|
332
|
-
when String
|
333
|
-
value.encode("UTF-8", invalid: :replace, undef: :replace, replace: "")
|
334
|
-
when Array
|
335
|
-
value.map { |v| ensure_utf8(v) }
|
336
|
-
when Hash
|
337
|
-
value.transform_keys do |k|
|
338
|
-
ensure_utf8(k)
|
339
|
-
end.transform_values { |v| ensure_utf8(v) }
|
340
|
-
else
|
341
|
-
value
|
429
|
+
adapter.new(representation).public_send(:"to_#{format}", options)
|
342
430
|
end
|
343
431
|
end
|
344
432
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "toml_object"
|
4
|
+
|
5
|
+
module Lutaml
|
6
|
+
module Model
|
7
|
+
module TomlAdapter
|
8
|
+
# Base class for TOML documents
|
9
|
+
class TomlDocument < TomlObject
|
10
|
+
def self.parse(toml)
|
11
|
+
raise NotImplementedError, "Subclasses must implement `parse`."
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_toml(*args)
|
15
|
+
raise NotImplementedError, "Subclasses must implement `to_toml`."
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lutaml
|
4
|
+
module Model
|
5
|
+
module TomlAdapter
|
6
|
+
# Base class for TOML objects
|
7
|
+
class TomlObject
|
8
|
+
attr_reader :attributes
|
9
|
+
|
10
|
+
def initialize(attributes = {})
|
11
|
+
@attributes = attributes
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](key)
|
15
|
+
@attributes[key]
|
16
|
+
end
|
17
|
+
|
18
|
+
def []=(key, value)
|
19
|
+
@attributes[key] = value
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_h
|
23
|
+
@attributes
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -1,18 +1,17 @@
|
|
1
|
-
# lib/lutaml/model/toml_adapter/toml_rb_adapter.rb
|
2
1
|
require "toml-rb"
|
3
|
-
require_relative "
|
2
|
+
require_relative "toml_document"
|
4
3
|
|
5
4
|
module Lutaml
|
6
5
|
module Model
|
7
6
|
module TomlAdapter
|
8
|
-
class
|
7
|
+
class TomlRbAdapter < TomlDocument
|
9
8
|
def self.parse(toml)
|
10
9
|
data = TomlRB.parse(toml)
|
11
10
|
new(data)
|
12
11
|
end
|
13
12
|
|
14
|
-
def to_toml(*
|
15
|
-
TomlRB.dump(to_h
|
13
|
+
def to_toml(*)
|
14
|
+
TomlRB.dump(to_h)
|
16
15
|
end
|
17
16
|
end
|
18
17
|
end
|
@@ -1,11 +1,10 @@
|
|
1
|
-
# lib/lutaml/model/toml_adapter/tomlib_adapter.rb
|
2
1
|
require "tomlib"
|
3
|
-
require_relative "
|
2
|
+
require_relative "toml_document"
|
4
3
|
|
5
4
|
module Lutaml
|
6
5
|
module Model
|
7
6
|
module TomlAdapter
|
8
|
-
class
|
7
|
+
class TomlibAdapter < TomlDocument
|
9
8
|
def self.parse(toml)
|
10
9
|
data = Tomlib.load(toml)
|
11
10
|
new(data)
|
@@ -1,37 +1,6 @@
|
|
1
|
-
# lib/lutaml/model/toml_adapter.rb
|
2
|
-
|
3
1
|
module Lutaml
|
4
2
|
module Model
|
5
3
|
module TomlAdapter
|
6
|
-
class TomlObject
|
7
|
-
attr_reader :attributes
|
8
|
-
|
9
|
-
def initialize(attributes = {})
|
10
|
-
@attributes = attributes
|
11
|
-
end
|
12
|
-
|
13
|
-
def [](key)
|
14
|
-
@attributes[key]
|
15
|
-
end
|
16
|
-
|
17
|
-
def []=(key, value)
|
18
|
-
@attributes[key] = value
|
19
|
-
end
|
20
|
-
|
21
|
-
def to_h
|
22
|
-
@attributes
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
class Document < TomlObject
|
27
|
-
def self.parse(toml)
|
28
|
-
raise NotImplementedError, "Subclasses must implement `parse`."
|
29
|
-
end
|
30
|
-
|
31
|
-
def to_toml(*args)
|
32
|
-
raise NotImplementedError, "Subclasses must implement `to_toml`."
|
33
|
-
end
|
34
|
-
end
|
35
4
|
end
|
36
5
|
end
|
37
6
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require "date"
|
2
|
+
|
3
|
+
module Lutaml
|
4
|
+
module Model
|
5
|
+
module Type
|
6
|
+
# Date and time representation
|
7
|
+
class DateTime
|
8
|
+
def self.cast(value)
|
9
|
+
return if value.nil?
|
10
|
+
|
11
|
+
::DateTime.parse(value.to_s).new_offset(0)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.serialize(value)
|
15
|
+
value.iso8601
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
module Lutaml
|
4
|
+
module Model
|
5
|
+
module Type
|
6
|
+
# JSON representation
|
7
|
+
class Json
|
8
|
+
attr_reader :value
|
9
|
+
|
10
|
+
def initialize(value)
|
11
|
+
@value = value
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_json(*_args)
|
15
|
+
@value.to_json
|
16
|
+
end
|
17
|
+
|
18
|
+
def ==(other)
|
19
|
+
@value == (other.is_a?(::Hash) ? other : other.value)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.cast(value)
|
23
|
+
return value if value.is_a?(self) || value.nil?
|
24
|
+
|
25
|
+
new(::JSON.parse(value))
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.serialize(value)
|
29
|
+
value.to_json
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -1,11 +1,12 @@
|
|
1
|
-
# lib/lutaml/model/type/time_without_date.rb
|
2
1
|
module Lutaml
|
3
2
|
module Model
|
4
3
|
module Type
|
4
|
+
# Time representation without date
|
5
5
|
class TimeWithoutDate
|
6
6
|
def self.cast(value)
|
7
|
-
|
8
|
-
|
7
|
+
return if value.nil?
|
8
|
+
|
9
|
+
::Time.parse(value.to_s)
|
9
10
|
end
|
10
11
|
|
11
12
|
def self.serialize(value)
|