diff --git a/lib/lutaml/model/mapping_rule.rb b/lib/lutaml/model/mapping_rule.rb index d8fb83d..e383b56 100644 --- a/lib/lutaml/model/mapping_rule.rb +++ b/lib/lutaml/model/mapping_rule.rb @@ -46,11 +46,13 @@ def serialize_attribute(model, element, doc) end end - def serialize(model, value) + def serialize(model, parent = nil, doc = nil) if custom_methods[:to] - model.send(custom_methods[:to], model, value) + model.send(custom_methods[:to], model, parent, doc) + elsif delegate + model.public_send(delegate).public_send(to) else - value + model.public_send(to) end end diff --git a/lib/lutaml/model/serialize.rb b/lib/lutaml/model/serialize.rb index 49cba2c..171dedb 100644 --- a/lib/lutaml/model/serialize.rb +++ b/lib/lutaml/model/serialize.rb @@ -40,11 +40,30 @@ def inherited(subclass) def model(klass = nil) if klass @model = klass + add_order_handling_methods_to_model(klass) else @model end end + def add_order_handling_methods_to_model(klass) + Utils.add_method_if_not_defined(klass, :ordered=) do |ordered| + @ordered = ordered + end + + Utils.add_method_if_not_defined(klass, :ordered?) do + !!@ordered + end + + Utils.add_method_if_not_defined(klass, :element_order=) do |order| + @element_order = order + end + + Utils.add_method_if_not_defined(klass, :element_order) do + @element_order + end + end + def cast(value) value end diff --git a/lib/lutaml/model/utils.rb b/lib/lutaml/model/utils.rb index 1dccf29..e528c9b 100644 --- a/lib/lutaml/model/utils.rb +++ b/lib/lutaml/model/utils.rb @@ -42,6 +42,14 @@ def blank?(value) value.respond_to?(:empty?) ? value.empty? : !value end + def add_method_if_not_defined(klass, method_name, &block) + unless klass.method_defined?(method_name) + klass.class_eval do + define_method(method_name, &block) + end + end + end + private def camelize_part(part) diff --git a/lib/lutaml/model/xml_adapter/nokogiri_adapter.rb b/lib/lutaml/model/xml_adapter/nokogiri_adapter.rb index 52aa690..9009d4f 100644 --- a/lib/lutaml/model/xml_adapter/nokogiri_adapter.rb +++ b/lib/lutaml/model/xml_adapter/nokogiri_adapter.rb @@ -68,7 +68,7 @@ def build_ordered_element(xml, element, options = {}) value = attribute_value_for(element, element_rule) if element_rule == xml_mapping.content_mapping - text = element.send(xml_mapping.content_mapping.to) + text = xml_mapping.content_mapping.serialize(element) text = text[curr_index] if text.is_a?(Array) prefixed_xml.text text diff --git a/lib/lutaml/model/xml_adapter/xml_document.rb b/lib/lutaml/model/xml_adapter/xml_document.rb index 47abed4..428adb9 100644 --- a/lib/lutaml/model/xml_adapter/xml_document.rb +++ b/lib/lutaml/model/xml_adapter/xml_document.rb @@ -206,7 +206,7 @@ def build_unordered_element(xml, element, options = {}) @root.send(content_rule.custom_methods[:to], element, prefixed_xml.parent, prefixed_xml) else - text = element.send(content_rule.to) + text = content_rule.serialize(element) text = text.join if text.is_a?(Array) prefixed_xml.add_text(xml, text) end diff --git a/spec/lutaml/model/custom_model_spec.rb b/spec/lutaml/model/custom_model_spec.rb index c1484f8..ccd55b5 100644 --- a/spec/lutaml/model/custom_model_spec.rb +++ b/spec/lutaml/model/custom_model_spec.rb @@ -58,6 +58,40 @@ def child_from_xml(model, value) end end +module CustomModelSpecs + class TextElement < Lutaml::Model::Serializable + attribute :sup, :string + attribute :sub, :string + attribute :text, :string + + xml do + root "text-element" + + map_content to: :text + + map_element "sup", to: :sup + map_element "sub", to: :sub + end + end + + class Id + attr_accessor :id + end + + class Docid < Lutaml::Model::Serializable + model Id + attribute :id, TextElement + + xml do + root "docid", mixed: true + + map_content to: :text, delegate: :id + map_element :sub, to: :sub, delegate: :id + map_element :sup, to: :sup, delegate: :id + end + end +end + RSpec.describe "CustomModel" do let(:parent_mapper) { CustomModelParentMapper } let(:child_mapper) { CustomModelChildMapper } @@ -272,6 +306,14 @@ def child_from_xml(model, value) expect(instance.child_mapper.street).to eq("Custom Avenue") expect(instance.child_mapper.city).to eq("New City") end + + it "uses delegate to for child mapper class" do + xml = "Str2text1123" + + docid = CustomModelSpecs::Docid.from_xml(xml) + + expect(CustomModelSpecs::Docid.to_xml(docid)).to eq(xml) + end end end end diff --git a/spec/lutaml/model/serializable_spec.rb b/spec/lutaml/model/serializable_spec.rb index b8bcdd7..132cbe8 100644 --- a/spec/lutaml/model/serializable_spec.rb +++ b/spec/lutaml/model/serializable_spec.rb @@ -68,9 +68,9 @@ class GlazeTechnique < Lutaml::Model::Serializable RSpec.describe Lutaml::Model::Serializable do describe ".model" do it "sets the model for the class" do - expect { described_class.model("Foo") }.to change(described_class, :model) + expect { described_class.model(TestModel) }.to change(described_class, :model) .from(nil) - .to("Foo") + .to(TestModel) end end