Module: Lutaml::Model::Schema::Templates

Defined in:
lib/lutaml/model/schema/templates.rb

Overview

Templates that are actually shared between schema compilers (XSD, RNG, future formats). Single-consumer templates live in the renderer that uses them — putting them here would just be relocation, not deduplication.

Each constant is an ERB.new(...) evaluated via TEMPLATE.result(binding) from a renderer that exposes the required hook methods (documented above each template).

Constant Summary collapse

SERIALIZABLE_CLASS =

Single shape for any Lutaml::Model::Serializable subclass generated by ANY schema compiler. There is no per-format variant — adding a new xml directive here propagates to every compiler that uses this template. Consumed by:

- Lutaml::Model::Schema::Renderers::Model
(renders XSD complex types / groups and RNG generated classes)

Required binding methods (renderer must expose all of these, returning "" / nil / false for inapplicable sections):

from ClassBoilerplate:
module_opening, module_closing,
registration_methods, registration_execution,
boilerplate_indent_str

identity / parent:
rendered_class_name                 String — CamelCase
serializable_class_parent           String — e.g. "Lutaml::Model::Serializable"

header:
serializable_class_required_files   String — `require_relative` lines or ""
serializable_class_documentation    String — doc comment block or ""

body — attribute declarations:
serializable_class_attributes       String — `attribute :foo, :bar` lines
serializable_class_imports          String — `import_model :foo` lines or ""

body — xml block:
xml_root_directive_line             String or nil — `element "X"` /
                                    `type_name "X"` / nil to skip
xml_namespace_line                  String or nil — `namespace ClassName` / nil
xml_mixed_content?                  Boolean — emit `mixed_content`
xml_text_content?                   Boolean — emit `map_content to: :content`
xml_attribute_mappings              String — `map_element`/`map_attribute` lines
xml_extra_mappings                  String — extra mapping lines or ""
                                    (e.g. XSD's simple_content tail)

ERB.new(<<~TMPL, trim_mode: "-")
  # frozen_string_literal: true

  require "lutaml/model"
  <%= serializable_class_required_files -%>
  <%= module_opening -%>
  <%= serializable_class_documentation -%>
  class <%= rendered_class_name %> < <%= serializable_class_parent %>
  <%= serializable_class_attributes -%>
  <%= serializable_class_imports -%>
  <%= "\n" if serializable_class_attributes.length.positive? || serializable_class_imports.length.positive? -%>
  <%= boilerplate_indent_str %>xml do
  <%- if xml_root_directive_line -%>
  <%= boilerplate_indent_str * 2 %><%= xml_root_directive_line %>
  <%- end -%>
  <%- if xml_namespace_line -%>
  <%= boilerplate_indent_str * 2 %><%= xml_namespace_line %>
  <%- end -%>
  <%- if xml_mixed_content? -%>
  <%= boilerplate_indent_str * 2 %>mixed_content
  <%- end -%>
  <%- if xml_text_content? -%>
  <%= boilerplate_indent_str * 2 %>map_content to: :content
  <%- end -%>
  <%= xml_attribute_mappings -%>
  <%= xml_extra_mappings -%>
  <%= boilerplate_indent_str %>end
  <%= registration_methods -%>
  end
  <%= module_closing -%>
  <%= registration_execution -%>
TMPL
XML_NAMESPACE =

XmlNamespace subclass. Consumed by:

- Lutaml::Model::Schema::Renderers::Namespace

Binding: module_opening, module_closing, class_name, uri, prefix_default.

ERB.new(<<~TMPL, trim_mode: "-")
  # frozen_string_literal: true

  require "lutaml/model"

  <%= module_opening -%>
  # Namespace: <%= uri %>
  class <%= class_name %> < Lutaml::Xml::W3c::XmlNamespace
    uri <%= uri.inspect %>
    prefix_default <%= prefix_default.inspect %>
  <%- if element_form_default_line -%>
    <%= element_form_default_line %>
  <%- end -%>
  end
  <%= module_closing -%>
TMPL
RESTRICTED_SIMPLE_TYPE =

Restricted simple-type subclass (cast method that mutates options with facets then delegates to super). Consumed by:

- Lutaml::Model::Schema::Renderers::RestrictedType

Binding: module_opening, module_closing, registration_methods, registration_execution, rendered_class_name, parent_class, xml_namespace_line, restricted_simple_type_required_files, restricted_simple_type_cast_body, boilerplate_indent_str.

ERB.new(<<~TMPL, trim_mode: "-")
  # frozen_string_literal: true
  require "lutaml/model"
  <%= restricted_simple_type_required_files -%>
  <%= module_opening -%>
  class <%= rendered_class_name %><%= " < \#{parent_class}" if parent_class %>
  <%- if xml_namespace_line -%>
  <%= boilerplate_indent_str %>xml do
  <%= boilerplate_indent_str * 2 %><%= xml_namespace_line %>
  <%= boilerplate_indent_str %>end
  <%- end -%>
  <%= boilerplate_indent_str %>def self.cast(value, options = {})
  <%= boilerplate_indent_str * 2 %>return if value.nil?

  <%= restricted_simple_type_cast_body -%>
  <%= boilerplate_indent_str * 2 %>value = super(value, options)
  <%= boilerplate_indent_str * 2 %>value
  <%= boilerplate_indent_str %>end
  <%= registration_methods -%>
  end
  <%= module_closing -%>
  <%= registration_execution -%>
TMPL
UNION_TYPE =

Lutaml::Model::Type::Value union subclass. Consumed by:

- Lutaml::Model::Schema::Renderers::Union

union_cast_body selects the cast strategy from the spec (XSD: ||-chained resolve_type; RNG: each+rescue).

ERB.new(<<~TMPL, trim_mode: "-")
  # frozen_string_literal: true
  require "lutaml/model"
  <%= union_required_files -%>
  <%= module_opening -%>
  class <%= rendered_class_name %> < Lutaml::Model::Type::Value
  <%= boilerplate_indent_str %>def self.cast(value, options = {})
  <%= boilerplate_indent_str * 2 %>return if value.nil?

  <%= union_cast_body -%>
  <%= boilerplate_indent_str %>end
  <%= registration_methods -%>
  end
  <%= module_closing -%>
  <%= registration_execution -%>
TMPL