lutaml-model 0.3.15 → 0.3.17

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 59ac2ffbc292a5e34dbbbf79441a8220a48954ba5acd21d2780235281bfbbee2
4
- data.tar.gz: 253892694acb1359120e6401d83e05bc2daa2f371b69f667210c048c08f2336c
3
+ metadata.gz: d8df6fb14ce661ef1c54be01a1b21c0f5e35937d701846807f036f2b97fdb06d
4
+ data.tar.gz: 92fcc49f083dcb5def7133c8e643ec17b88fd216150061c2c76bf40183f550d3
5
5
  SHA512:
6
- metadata.gz: 920de33ce2cc20336fa2ed87c3a2d5743f4016c8a400a881c91e4eafee0452e3fdc110429f3e71b7216f84694e546b26848c50323bc25397d32c8a1aa2e6901e
7
- data.tar.gz: 3685a35624c0c355ee457241a308bf9e46c37c9a7b14994948a897c9210a13229c2a2832d8f595b2d83a4bf96660f1ea2b9843c83ea8ba9a73978ef67e864818
6
+ metadata.gz: d701f87c169faa98f952f2ce669ae42721462f512b729caab789a120055b90e19507bcad012bb7ecd57b912fc5984b6a70b59f305c58d5b1a0c341a4c035118f
7
+ data.tar.gz: d2c411bd20127d21d1c9183cf485945e28288b54e6a45399b9e20c3eb9ca5157fa42b025f924a0a845d905e9db09de0d6ac28a136d8176e39a2d756b19a4729a
data/.rubocop_todo.yml CHANGED
@@ -1,12 +1,12 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2024-10-23 12:15:48 UTC using RuboCop version 1.66.1.
3
+ # on 2024-10-28 08:29:46 UTC using RuboCop version 1.66.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
7
7
  # versions of RuboCop, may require this file to be generated again.
8
8
 
9
- # Offense count: 139
9
+ # Offense count: 148
10
10
  # This cop supports safe autocorrection (--autocorrect).
11
11
  # Configuration parameters: Max, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns.
12
12
  # URISchemes: http, https
@@ -69,7 +69,7 @@ Metrics/CyclomaticComplexity:
69
69
  Metrics/MethodLength:
70
70
  Max: 51
71
71
 
72
- # Offense count: 4
72
+ # Offense count: 6
73
73
  # Configuration parameters: CountKeywordArgs, MaxOptionalParameters.
74
74
  Metrics/ParameterLists:
75
75
  Max: 13
@@ -85,7 +85,7 @@ Metrics/PerceivedComplexity:
85
85
  - 'lib/lutaml/model/xml_adapter/ox_adapter.rb'
86
86
  - 'lib/lutaml/model/xml_adapter/xml_document.rb'
87
87
 
88
- # Offense count: 8
88
+ # Offense count: 9
89
89
  # Configuration parameters: Prefixes, AllowedPatterns.
90
90
  # Prefixes: when, with, without
91
91
  RSpec/ContextWording:
@@ -125,7 +125,7 @@ RSpec/MultipleDescribes:
125
125
  - 'spec/lutaml/model/xml_adapter/xml_namespace_spec.rb'
126
126
  - 'spec/lutaml/model/xml_adapter_spec.rb'
127
127
 
128
- # Offense count: 119
128
+ # Offense count: 125
129
129
  RSpec/MultipleExpectations:
130
130
  Max: 14
131
131
 
@@ -134,6 +134,11 @@ RSpec/MultipleExpectations:
134
134
  RSpec/MultipleMemoizedHelpers:
135
135
  Max: 9
136
136
 
137
+ # Offense count: 4
138
+ # Configuration parameters: AllowedGroups.
139
+ RSpec/NestedGroups:
140
+ Max: 4
141
+
137
142
  # Offense count: 7
138
143
  RSpec/PendingWithoutReason:
139
144
  Exclude:
@@ -153,13 +158,14 @@ RSpec/RepeatedExampleGroupDescription:
153
158
  Exclude:
154
159
  - 'spec/lutaml/model/collection_spec.rb'
155
160
 
156
- # Offense count: 2
161
+ # Offense count: 3
157
162
  # Configuration parameters: Include, CustomTransform, IgnoreMethods, IgnoreMetadata.
158
163
  # Include: **/*_spec.rb
159
164
  RSpec/SpecFilePathFormat:
160
165
  Exclude:
161
166
  - '**/spec/routing/**/*'
162
167
  - 'spec/lutaml/model/collection_spec.rb'
168
+ - 'spec/lutaml/model/defaults_spec.rb'
163
169
  - 'spec/lutaml/model/type/decimal_spec.rb'
164
170
 
165
171
  # Offense count: 1
data/README.adoc CHANGED
@@ -390,7 +390,7 @@ acceptance of the newly updated component.
390
390
  ====
391
391
 
392
392
 
393
- === Attribute value default
393
+ === Attribute value default and rendering defaults
394
394
 
395
395
  Specify default values for attributes using the `default` option.
396
396
  The `default` option can be set to a value or a lambda that returns a value.
@@ -423,6 +423,81 @@ end
423
423
  ----
424
424
  ====
425
425
 
426
+ The "default behavior" (pun intended) is to not render a default value if
427
+ the current value is the same as the default value.
428
+
429
+ In certain cases, it is necessary to render the default value even if the
430
+ current value is the same as the default value. This can be achieved by setting
431
+ the `render_default` option to `true`.
432
+
433
+ Syntax:
434
+
435
+ [source,ruby]
436
+ ----
437
+ attribute :name_of_attribute, Type, default: -> { value }, render_default: true
438
+ ----
439
+
440
+ .Using the `render_default` option to force encoding the default value
441
+ [example]
442
+ ====
443
+ [source,ruby]
444
+ ----
445
+ class Glaze < Lutaml::Model::Serializable
446
+ attribute :color, :string, default: -> { 'Clear' }
447
+ attribute :opacity, :string, default: -> { 'Opaque' }
448
+ attribute :temperature, :integer, default: -> { 1050 }
449
+ attribute :firing_time, :integer, default: -> { 60 }
450
+
451
+ xml do
452
+ root "glaze"
453
+ map_element 'color', to: :color
454
+ map_element 'opacity', to: :opacity, render_default: true
455
+ map_attribute 'temperature', to: :temperature
456
+ map_attribute 'firingTime', to: :firing_time, render_default: true
457
+ end
458
+
459
+ json do
460
+ map 'color', to: :color
461
+ map 'opacity', to: :opacity, render_default: true
462
+ map 'temperature', to: :temperature
463
+ map 'firingTime', to: :firing_time, render_default: true
464
+ end
465
+ end
466
+ ----
467
+ ====
468
+
469
+ .Attributes with `render_default: true` are rendered when the value is identical to the default
470
+ [example]
471
+ ====
472
+ [source,ruby]
473
+ ----
474
+ > glaze_new = Glaze.new
475
+ > puts glaze_new.to_xml
476
+ # <glaze firingTime="60">
477
+ # <opacity>Opaque</opacity>
478
+ # </glaze>
479
+ > puts glaze_new.to_json
480
+ # {"firingTime":60,"opacity":"Opaque"}
481
+ ----
482
+ ====
483
+
484
+ .Attributes with `render_default: true` with non-default values are rendered
485
+ [example]
486
+ ====
487
+ [source,ruby]
488
+ ----
489
+ > glaze = Glaze.new(color: 'Celadon', opacity: 'Semitransparent', temperature: 1300, firing_time: 90)
490
+ > puts glaze.to_xml
491
+ # <glaze color="Celadon" temperature="1300" firingTime="90">
492
+ # <opacity>Semitransparent</opacity>
493
+ # </glaze>
494
+ > puts glaze.to_json
495
+ # {"color":"Celadon","temperature":1300,"firingTime":90,"opacity":"Semitransparent"}
496
+ ----
497
+ ====
498
+
499
+
500
+
426
501
  === Attribute as raw string
427
502
 
428
503
  An attribute can be set to read the value as raw string for XML, by using the `raw: true` option.
@@ -667,9 +742,12 @@ end
667
742
  > Example.new(value: 12).to_xml
668
743
  > #<example value="12"></example>
669
744
  ----
745
+ ====
746
+
747
+ The `map_attribute` method does not inherit the root element's namespace.
748
+ To specify a namespace for an attribute, please explicitly declare the
749
+ *namespace* and *prefix* in the `map_attribute` method.
670
750
 
671
- The map_attribute method does not inherit the root element's namespace. If you need to specify a namespace for an attribute,
672
- you must explicitly declare the namespace and prefix in the map_attribute method.
673
751
  [example]
674
752
  ====
675
753
  The following class will parse the XML snippet below:
@@ -1081,7 +1159,7 @@ end
1081
1159
  ----
1082
1160
  ====
1083
1161
 
1084
- TODO: How to create mixed content from `#new`?
1162
+ // TODO: How to create mixed content from `#new`?
1085
1163
 
1086
1164
  [[xml-schema-location]]
1087
1165
  ==== Automatic support of `xsi:schemaLocation`
@@ -2020,7 +2098,9 @@ Lutaml::Model::Config.configure do |config|
2020
2098
  end
2021
2099
  ----
2022
2100
 
2023
- NOTE: By default `yaml_adapter_type` and `json_adapter_type` are set to `:standard_yaml` and `:standard_json` respectively.
2101
+ NOTE: By default `yaml_adapter_type` and `json_adapter_type` are set to
2102
+ `:standard_yaml` and `:standard_json` respectively.
2103
+
2024
2104
 
2025
2105
  === XML
2026
2106
 
@@ -3,10 +3,20 @@ module Lutaml
3
3
  class Attribute
4
4
  attr_reader :name, :type, :options
5
5
 
6
+ ALLOWED_OPTIONS = %i[
7
+ raw
8
+ default
9
+ delegate
10
+ collection
11
+ values
12
+ ].freeze
13
+
6
14
  def initialize(name, type, options = {})
7
15
  @name = name
8
16
  @type = cast_type(type)
9
17
  @options = options
18
+ validate_options!
19
+
10
20
  @raw = !!options[:raw]
11
21
 
12
22
  if collection?
@@ -54,10 +64,6 @@ module Lutaml
54
64
  @raw
55
65
  end
56
66
 
57
- def render_default?
58
- !!@options[:render_default]
59
- end
60
-
61
67
  def default
62
68
  value = if delegate
63
69
  type.attributes[to].default
@@ -70,10 +76,6 @@ module Lutaml
70
76
  cast_value(value)
71
77
  end
72
78
 
73
- def render_nil?
74
- options.fetch(:render_nil, false)
75
- end
76
-
77
79
  def enum_values
78
80
  @options.key?(:values) ? @options[:values] : []
79
81
  end
@@ -207,6 +209,14 @@ module Lutaml
207
209
  Lutaml::Model::Type.cast(value, type)
208
210
  end
209
211
  end
212
+
213
+ private
214
+
215
+ def validate_options!
216
+ if (options = @options.keys - ALLOWED_OPTIONS).any?
217
+ raise StandardError, "Invalid options given for `#{name}` #{options}"
218
+ end
219
+ end
210
220
  end
211
221
  end
212
222
  end
@@ -13,6 +13,7 @@ module Lutaml
13
13
  name,
14
14
  to: nil,
15
15
  render_nil: false,
16
+ render_default: false,
16
17
  with: {},
17
18
  delegate: nil,
18
19
  child_mappings: nil
@@ -23,6 +24,7 @@ module Lutaml
23
24
  name,
24
25
  to: to,
25
26
  render_nil: render_nil,
27
+ render_default: render_default,
26
28
  with: with,
27
29
  delegate: delegate,
28
30
  child_mappings: child_mappings,
@@ -9,6 +9,7 @@ module Lutaml
9
9
  name,
10
10
  to:,
11
11
  render_nil: false,
12
+ render_default: false,
12
13
  with: {},
13
14
  delegate: nil,
14
15
  child_mappings: nil
@@ -17,6 +18,7 @@ module Lutaml
17
18
  name,
18
19
  to: to,
19
20
  render_nil: render_nil,
21
+ render_default: render_default,
20
22
  with: with,
21
23
  delegate: delegate,
22
24
  )
@@ -40,35 +40,30 @@ module Lutaml
40
40
  def model(klass = nil)
41
41
  if klass
42
42
  @model = klass
43
- add_order_handling_methods_to_model(klass)
43
+ add_custom_handling_methods_to_model(klass)
44
44
  else
45
45
  @model
46
46
  end
47
47
  end
48
48
 
49
- def add_order_handling_methods_to_model(klass)
50
- Utils.add_method_if_not_defined(klass, :ordered=) do |ordered|
51
- @ordered = ordered
52
- end
53
-
54
- Utils.add_method_if_not_defined(klass, :ordered?) do
55
- !!@ordered
56
- end
57
-
58
- Utils.add_method_if_not_defined(klass, :mixed=) do |mixed|
59
- @mixed = mixed
60
- end
49
+ def add_custom_handling_methods_to_model(klass)
50
+ Utils.add_boolean_accessor_if_not_defined(klass, :ordered)
51
+ Utils.add_boolean_accessor_if_not_defined(klass, :mixed)
52
+ Utils.add_accessor_if_not_defined(klass, :element_order)
61
53
 
62
- Utils.add_method_if_not_defined(klass, :mixed?) do
63
- !!@mixed
54
+ Utils.add_method_if_not_defined(klass, :using_default_for) do |attribute_name|
55
+ @using_default ||= {}
56
+ @using_default[attribute_name] = true
64
57
  end
65
58
 
66
- Utils.add_method_if_not_defined(klass, :element_order=) do |order|
67
- @element_order = order
59
+ Utils.add_method_if_not_defined(klass, :value_set_for) do |attribute_name|
60
+ @using_default ||= {}
61
+ @using_default[attribute_name] = false
68
62
  end
69
63
 
70
- Utils.add_method_if_not_defined(klass, :element_order) do
71
- @element_order
64
+ Utils.add_method_if_not_defined(klass, :using_default?) do |attribute_name|
65
+ @using_default ||= {}
66
+ !!@using_default[attribute_name]
72
67
  end
73
68
  end
74
69
 
@@ -160,6 +155,7 @@ module Lutaml
160
155
  mappings.each_with_object({}) do |rule, hash|
161
156
  name = rule.to
162
157
  next if except&.include?(name) || (only && !only.include?(name))
158
+ next if !rule.render_default? && instance.using_default?(rule.to)
163
159
 
164
160
  next handle_delegate(instance, rule, hash, format) if rule.delegate
165
161
 
@@ -224,11 +220,10 @@ module Lutaml
224
220
  klass = format == :xml ? XmlMapping : KeyValueMapping
225
221
 
226
222
  klass.new.tap do |mapping|
227
- attributes&.each do |name, attr|
223
+ attributes&.each_key do |name|
228
224
  mapping.map_element(
229
225
  name.to_s,
230
226
  to: name,
231
- render_nil: attr.render_nil?,
232
227
  )
233
228
  end
234
229
 
@@ -351,7 +346,7 @@ module Lutaml
351
346
  end
352
347
 
353
348
  defaults_used.each do |attribute_name|
354
- instance.using_default_for(attribute_name) if instance.respond_to?(:using_default_for)
349
+ instance.using_default_for(attribute_name)
355
350
  end
356
351
 
357
352
  instance
@@ -50,6 +50,34 @@ module Lutaml
50
50
  end
51
51
  end
52
52
 
53
+ def add_accessor_if_not_defined(klass, attribute)
54
+ add_getter_if_not_defined(klass, attribute)
55
+ add_setter_if_not_defined(klass, attribute)
56
+ end
57
+
58
+ def add_boolean_accessor_if_not_defined(klass, attribute)
59
+ add_boolean_getter_if_not_defined(klass, attribute)
60
+ add_setter_if_not_defined(klass, attribute)
61
+ end
62
+
63
+ def add_getter_if_not_defined(klass, attribute)
64
+ add_method_if_not_defined(klass, attribute) do
65
+ instance_variable_get(:"@__#{attribute}")
66
+ end
67
+ end
68
+
69
+ def add_boolean_getter_if_not_defined(klass, attribute)
70
+ add_method_if_not_defined(klass, "#{attribute}?") do
71
+ !!instance_variable_get(:"@__#{attribute}")
72
+ end
73
+ end
74
+
75
+ def add_setter_if_not_defined(klass, attribute)
76
+ add_method_if_not_defined(klass, "#{attribute}=") do |value|
77
+ instance_variable_set(:"@__#{attribute}", value)
78
+ end
79
+ end
80
+
53
81
  def deep_dup(hash)
54
82
  return hash if hash.nil?
55
83
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Lutaml
4
4
  module Model
5
- VERSION = "0.3.15"
5
+ VERSION = "0.3.17"
6
6
  end
7
7
  end
@@ -49,6 +49,7 @@ module Lutaml
49
49
  end
50
50
 
51
51
  tag_name = options[:tag_name] || xml_mapping.root_element
52
+ tag_name = "#{tag_name}_" if prefixed_xml.respond_to?(tag_name)
52
53
  prefixed_xml.public_send(tag_name, attributes) do
53
54
  if options.key?(:namespace_prefix) && !options[:namespace_prefix]
54
55
  xml.parent.namespace = nil
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lutaml-model
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.15
4
+ version: 0.3.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-10-26 00:00:00.000000000 Z
11
+ date: 2024-10-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor