Module: Metaschema::ModelGenerator::Utils

Defined in:
lib/metaschema/model_generator/utils.rb

Overview

Shared utility methods extracted from ModelGenerator. Used by FieldFactory, AssemblyFactory, and ModelGenerator itself.

Constant Summary collapse

RESERVED_WORDS =
%i[class module method hash object_id nil? is_a? kind_of?
instance_of? respond_to? send].freeze

Class Method Summary collapse

Class Method Details

.create_model(name, super_class = Lutaml::Model::Serializable) ⇒ Object

Create an anonymous class with a debuggable temporary name.



33
34
35
36
37
# File 'lib/metaschema/model_generator/utils.rb', line 33

def self.create_model(name, super_class = Lutaml::Model::Serializable)
  model = Class.new(super_class)
  set_model_temporary_name(model, name)
  model
end

.model?(object) ⇒ Boolean

Check if an object is a lutaml-model Serializable subclass.

Returns:

  • (Boolean)


40
41
42
# File 'lib/metaschema/model_generator/utils.rb', line 40

def self.model?(object)
  object.is_a?(Class) && object.include?(Lutaml::Model::Serialize)
end

.safe_attr(name) ⇒ Object

Convert a Metaschema name (hyphenated) to a safe Ruby attribute name.



12
13
14
15
# File 'lib/metaschema/model_generator/utils.rb', line 12

def self.safe_attr(name)
  sym = name.gsub("-", "_").to_sym
  RESERVED_WORDS.include?(sym) ? :"#{sym}_attr" : sym
end

.scoped_field_name(field_name, parent_name = nil) ⇒ Object

Generate a scoped name for inline field classes to avoid collisions.



24
25
26
27
28
29
30
# File 'lib/metaschema/model_generator/utils.rb', line 24

def self.scoped_field_name(field_name, parent_name = nil)
  if parent_name
    "Field_#{parent_name}_#{field_name.gsub('-', '_')}"
  else
    "Field_#{field_name.gsub('-', '_')}"
  end
end

.set_model_temporary_name(model, name) ⇒ Object

Assign a human-readable name to an anonymous class for debugging.



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/metaschema/model_generator/utils.rb', line 45

def self.set_model_temporary_name(model, name)
  display_name = name.gsub(/(?:^|[-._]+)./) do |n|
    n[-1].upcase
  end + ":Class"

  if model.respond_to?(:set_temporary_name)
    model.set_temporary_name(display_name)
    return
  end

  model.class_eval <<~RUBY, __FILE__, __LINE__ + 1
    def self.to_s
      name || #{display_name.inspect}
    end
    singleton_class.alias_method :inspect, :to_s
  RUBY
end

.unbounded?(max_occurs) ⇒ Boolean

Check if a max-occurs value represents an unbounded collection.

Returns:

  • (Boolean)


18
19
20
21
# File 'lib/metaschema/model_generator/utils.rb', line 18

def self.unbounded?(max_occurs)
  max_occurs.nil? || max_occurs == "unbounded" ||
    (max_occurs.respond_to?(:to_i) && max_occurs.to_i > 1)
end