Module: Lutaml::Model::Serialize::Builder

Included in:
Lutaml::Model::Serialize
Defined in:
lib/lutaml/model/serialize/builder.rb

Overview

Builder interface for constructing model instances with mixed content.

Provides two syntaxes:

NO MAGIC (Explicit Receiver)

group = Group.new do |g|
g.member(person1)
g.member_key("john")
g.description "\n  He is a good man.\n"
end

MAGIC (instance_eval — No Receiver)

group = Group.new do
member(person1)
member_key("john")
description "\n  He is a good man.\n"
end

Both syntaxes track the order of calls for mixed_content serialization.

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *args, &block) ⇒ Object (private)

Intercept method calls to track order for mixed_content



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/lutaml/model/serialize/builder.rb', line 81

def method_missing(method_name, *args, &block)
  # Check if this is an attribute setter call
  setter_name = :"#{method_name}="
  if args.length == 1 && attribute_exist?(setter_name)
    # Track order before calling the actual setter
    track_order(method_name, args.first, block) if @__order_tracking__

    # Call the actual setter
    send(setter_name, args.first)
  elsif args.empty? && block
    # Block form: attribute { |nested| nested.attr value }
    # This handles nested model construction
    handle_nested_block(method_name, block)
  else
    super
  end
end

Instance Method Details

#initialize(attrs = {}, options = {}, &block) ⇒ Object

Override initialize to support builder block syntax.

When a block is passed, evaluates it in the model's context. For mixed_content models, tracks call order in element_order.

Parameters:

  • attrs (Hash) (defaults to: {})

    Attribute values (ignored when block given)

  • options (Hash) (defaults to: {})

    Options (ignored when block given)

  • block (Proc, nil)

    Optional builder block



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/lutaml/model/serialize/builder.rb', line 36

def initialize(attrs = {}, options = {}, &block)
  # Call parent initialize
  super(attrs, options)

  return self unless block

  # Enable order tracking for ordered and mixed_content models.
  # `ordered?` is true for both `ordered` and `mixed_content`
  # (mixed_content sets @ordered = true in addition to @mixed_content).
  @__order_tracking__ = ordered?

  # Evaluate the block - use instance_eval for no-receiver style
  # The block's first parameter determines the style:
  # - |g| -> explicit receiver (block.call(g))
  # - no param -> instance_eval (&block)
  if block.arity.zero?
    instance_eval(&block)
  else
    yield(self)
  end

  self
end

#mixed_content?Boolean

Check if this model has mixed_content enabled

Returns:

  • (Boolean)


62
63
64
65
# File 'lib/lutaml/model/serialize/builder.rb', line 62

def mixed_content?
  mapping = self.class.mappings_for(:xml, lutaml_register)
  mapping&.mixed_content? || false
end

#ordered?Boolean

Check if this model has ordered or mixed_content enabled. Both set @ordered = true on the XML mapping; mixed_content additionally sets @mixed_content = true. Order tracking is needed for either mode so the builder can emit elements in setter-call order rather than declaration order.

Returns:

  • (Boolean)


73
74
75
76
# File 'lib/lutaml/model/serialize/builder.rb', line 73

def ordered?
  mapping = self.class.mappings_for(:xml, lutaml_register)
  mapping&.ordered? || false
end