lutaml-model 0.8.116 → 0.8.118

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: bd6d747592ab333f3edefaf4af21e7db87189a39c541bd7c70dda87b544615d8
4
- data.tar.gz: 2380f18d9b82122602c3afc60695dd2077c2cc125375032673f90721d152fa53
3
+ metadata.gz: c5849a4dbcad4fe94ec8f0da69f267dd03eb3d4fdba34515dbc7bad37362e31e
4
+ data.tar.gz: 0f3b29692d38dc196c88721d7fbb3d05839f405701e3863f0ced62cc693ca1a6
5
5
  SHA512:
6
- metadata.gz: d15bea65d1270d4eda9e07bbac48cee6232da11aab2df7bcbd51e74ab1ec8d9ecf2eb217b1b9d302cfdf128a2b51b610bd1062e7bfea1a81a65f68d16f952c43
7
- data.tar.gz: 976d507e33e4a79de59b767215279bee14aaba443a05bfb8c84918190e236faa19d4383af9a0b3b20c3743dbd95e47404967b37a0611619738bd9fe4667af6bb
6
+ metadata.gz: 4dccd043421013a6d07dfe20eb2082cc08187d1775dfdb8a3480ce8c1733df06c651c133e9114f94f18a3e1747a038cc22e2a5182f7f6212b263e7da15b7a17d
7
+ data.tar.gz: c2167269f36cd4d01af8595f4e0a8465614702aa66cb2881bb8cdbf497f0760b4397afee288c93355febdd1f2ffba1f76466ddbc6e3420bec6df35f4169bffae
@@ -5,6 +5,20 @@ module Lutaml
5
5
  class Attribute
6
6
  attr_reader :name, :options
7
7
 
8
+ # Format scalars a mapped-model attribute may be handed in the
9
+ # key-value lanes (#978). Adapter element nodes and other object
10
+ # forms belong to the mapping lane and must not divert.
11
+ SCALAR_CAST_TYPES = [
12
+ ::String,
13
+ ::Numeric,
14
+ ::Symbol,
15
+ ::Time,
16
+ ::Date,
17
+ ::DateTime,
18
+ ::TrueClass,
19
+ ::FalseClass,
20
+ ].freeze
21
+
8
22
  include CollectionHandler
9
23
  include DeepDupable
10
24
  include RestrictionValidation
@@ -982,9 +996,11 @@ instance_object = nil)
982
996
  # String, #978). A type declaring its own .cast owns scalar
983
997
  # construction; base-cast identity types fall through to the
984
998
  # legacy conversion chain, whose parse error names the token.
999
+ # Non-scalar input (adapter elements, hashes, arrays) rides
1000
+ # the mapping lane untouched.
985
1001
  if serializable_type?(register) && !value.nil? &&
986
- !value.is_a?(::Hash) && !value.is_a?(::Array) &&
987
- !value.respond_to?(:key?) && klass.respond_to?(:cast) &&
1002
+ SCALAR_CAST_TYPES.any? { |type| value.is_a?(type) } &&
1003
+ klass.respond_to?(:cast) &&
988
1004
  klass.method(:cast).owner == klass.singleton_class
989
1005
  casted = klass.cast(value)
990
1006
  return casted if casted.is_a?(klass)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Lutaml
4
4
  module Model
5
- VERSION = "0.8.116"
5
+ VERSION = "0.8.118"
6
6
  end
7
7
  end
@@ -485,8 +485,12 @@ module Lutaml
485
485
  # namespace). Contested names dispatch strictly by
486
486
  # (URI, local), falling back to URI-less rows.
487
487
  name = object.name
488
+ # Order entries may carry names with no mapped row (the
489
+ # parse records every child in document order); the
490
+ # layout cache kills its default proc to stay
491
+ # mutation-free, so a miss reads nil and drops below.
488
492
  keys = name_keys[name]
489
- if keys.length == 1
493
+ if keys&.length == 1
490
494
  dispatch_key = keys.first
491
495
  entry = rows_by_name[dispatch_key]
492
496
  else
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ # The scalar-cast diversion (#978) must not capture element-form input:
6
+ # a type declaring its own .cast still receives parsed child elements
7
+ # through the mapping lane, which builds the model from its XML
8
+ # mapping. Diverting those into .cast raised IncorrectModelError
9
+ # downstream (uniword shared-schemas round-trips on 0.8.116/0.8.117).
10
+ RSpec.describe "cast routing for element-form input" do
11
+ let(:styled_class) do
12
+ Class.new(Lutaml::Model::Serializable) do
13
+ attribute :value, :string
14
+
15
+ xml do
16
+ element "style"
17
+ map_attribute "value", to: :value
18
+ end
19
+
20
+ key_value do
21
+ map "value", to: :value
22
+ end
23
+
24
+ def self.cast(value)
25
+ return value if value.is_a?(self)
26
+
27
+ new(value: value.to_s)
28
+ end
29
+ end
30
+ end
31
+
32
+ let(:host_class) do
33
+ Class.new(Lutaml::Model::Serializable) do
34
+ attribute :style, "CastStyled"
35
+
36
+ xml do
37
+ element "host"
38
+ map_element "style", to: :style
39
+ end
40
+ end
41
+ end
42
+
43
+ before do
44
+ stub_const("CastStyled", styled_class)
45
+ stub_const("CastHost", host_class)
46
+ end
47
+
48
+ it "builds element-form input through the mapping lane" do
49
+ model = CastHost.from_xml('<host><style value="normal"/></host>')
50
+
51
+ expect(model.style).to be_a(CastStyled)
52
+ expect(model.style.value).to eq("normal")
53
+ end
54
+ end
@@ -516,6 +516,28 @@ RSpec.describe "XML plan fast path" do
516
516
  expect(fast_out).to include(%(<para kind="a">Hi <emph>there</emph> bye <emph>again</emph>!</para>))
517
517
  end
518
518
 
519
+ it "drops order entries whose names have no mapped row" do
520
+ klass = Class.new(Lutaml::Model::Serializable) do
521
+ attribute :a, :string, collection: true
522
+
523
+ xml do
524
+ element "d"
525
+ ordered
526
+ map_element "a", to: :a
527
+ end
528
+ end
529
+ xml = %(<d><a>1</a><note>extra</note><a>2</a></d>)
530
+
531
+ Lutaml::Model::Config.instance.xml_plan_fast_path = false
532
+ interp = klass.from_xml(xml).to_xml
533
+ Lutaml::Model::Config.instance.xml_plan_fast_path = true
534
+ fast_out = klass.from_xml(xml).to_xml
535
+ Lutaml::Model::Config.instance.xml_plan_fast_path = false
536
+
537
+ expect(fast_out).to eq(interp)
538
+ expect(fast_out).to eq("<d>\n <a>1</a>\n <a>2</a>\n</d>")
539
+ end
540
+
519
541
  it "reflects content mutations through the ordered fast serializer" do
520
542
  para = Class.new(Lutaml::Model::Serializable) do
521
543
  attribute :emph, :string, collection: true
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.8.116
4
+ version: 0.8.118
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-10-19 00:00:00.000000000 Z
11
+ date: 2026-10-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base64
@@ -1713,6 +1713,7 @@ files:
1713
1713
  - spec/lutaml/model/boot_manifest_spec.rb
1714
1714
  - spec/lutaml/model/cached_type_resolver_spec.rb
1715
1715
  - spec/lutaml/model/cardinality_strict_spec.rb
1716
+ - spec/lutaml/model/cast_element_form_spec.rb
1716
1717
  - spec/lutaml/model/cdata_spec.rb
1717
1718
  - spec/lutaml/model/choice_restrict_spec.rb
1718
1719
  - spec/lutaml/model/choice_spec.rb