Module: Minitwin::ClassMethods::Constructors

Included in:
Minitwin::ClassMethods
Defined in:
lib/minitwin/class_methods/constructors.rb

Instance Method Summary collapse

Instance Method Details

#collectionsObject

: () -> Hash[untyped, untyped]



14
15
16
# File 'lib/minitwin/class_methods/constructors.rb', line 14

def collections
  @collections ||= {}
end

#enrich_attribute_from_models(attributes, models, key, is_collection:) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/minitwin/class_methods/constructors.rb', line 104

def enrich_attribute_from_models(attributes, models, key, is_collection:)
  # Only enrich when attribute is missing or nil
  return if attributes.key?(key) && !attributes[key].nil?

  models.each_value do |model|
    next unless model.respond_to?(key)

    val = model.public_send(key)
    next if val.nil?

    attributes[key] = is_collection ? coerce_collection_array(val) : val
    break
  end
end

#enrich_attributes_from_models!(attributes, models) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/minitwin/class_methods/constructors.rb', line 91

def enrich_attributes_from_models!(attributes, models)
  properties.each_key do |key|
    enrich_attribute_from_models(attributes, models, key, is_collection: false)
  end

  collections.each_key do |key|
    enrich_attribute_from_models(attributes, models, key, is_collection: true)
  end
rescue StandardError
  # Expected: Model objects may raise in attribute readers or have unexpected
  # behavior. Be resilient and proceed with best-effort enrichment.
end

#from_collection(models) ⇒ Object

: (Array models) -> Array



82
83
84
# File 'lib/minitwin/class_methods/constructors.rb', line 82

def from_collection(models)
  models.map { |item| from_objects(model: item) }
end

#from_hash(args) ⇒ Object

: (Hash[untyped, untyped] args) -> instance



19
20
21
# File 'lib/minitwin/class_methods/constructors.rb', line 19

def from_hash(args)
  new(**args)
end

#from_json(body) ⇒ Object

: (String body) -> instance



24
25
26
27
# File 'lib/minitwin/class_methods/constructors.rb', line 24

def from_json(body)
  hash = JSON.parse(body, symbolize_names: true)
  from_hash(hash)
end

#from_object(model) ⇒ Object

: (untyped model) -> instance



40
41
42
43
44
45
46
47
48
49
# File 'lib/minitwin/class_methods/constructors.rb', line 40

def from_object(model)
  if model.is_a?(Hash)
    raise(
      "Input is not an object. If you want to instantiate a Minitwin with multiple " \
        "objects, then use the pluralized 'from_objects'-method."
    )
  end

  from_objects(model:)
end

#from_objects(**models) ⇒ Object

: (Hash[Symbol, untyped] **models) -> instance



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/minitwin/class_methods/constructors.rb', line 52

def from_objects(**models)
  attributes =
    models.values.map do |model|
      if model.respond_to?(:attributes) && model.respond_to?(:attribute_aliases)
        combined_attributes = model.attributes.dup
        model.attribute_aliases.each do |alias_name, real_attr|
          combined_attributes[alias_name] = model.send(real_attr)
        end
        combined_attributes
      elsif model.respond_to?(:to_h)
        model.to_h
      elsif model.respond_to?(:attributes)
        model.attributes
      else
        extract_instance_variables(model)
      end
    end.reduce({}, :merge)

  # Enrich attributes with relation-style readers (e.g., has_one/has_many)
  # when they are not present in the model's attributes hash. This allows
  # nested block/twin properties and collections to be populated from
  # object readers commonly used by ORMs like ActiveRecord.
  enrich_attributes_from_models!(attributes, models)

  obj = new(**attributes)
  models.each { |name, model| obj.instance_variable_set(internal_model_name(name), model) }
  obj
end

#from_params(params) ⇒ Object

Actually, this is expected to be an ‘ActionController::Parameters` object. The type will be unknown when used without rails. So for RBS the argument is typed `untyped`. : (untyped params) -> instance



33
34
35
36
37
# File 'lib/minitwin/class_methods/constructors.rb', line 33

def from_params(params)
  return from_hash(params) unless params.respond_to?(:to_unsafe_h)

  from_hash params.to_unsafe_h
end

#internal_model_name(name) ⇒ Object

: (Symbol name) -> String | nil



87
88
89
# File 'lib/minitwin/class_methods/constructors.rb', line 87

def internal_model_name(name)
  "#{Minitwin::INTERNAL_MODEL_PREFIX}#{name}" unless name.nil?
end

#propertiesObject

: () -> Hash[untyped, untyped]



9
10
11
# File 'lib/minitwin/class_methods/constructors.rb', line 9

def properties
  @properties ||= {}
end