Class: ROM::Factory::TupleEvaluator Private

Inherits:
Object
  • Object
show all
Defined in:
lib/rom/factory/tuple_evaluator.rb

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Defined Under Namespace

Classes: TupleEvaluatorError

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attributes, relation, traits = {}) ⇒ TupleEvaluator

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of TupleEvaluator.

[View source]

45
46
47
48
49
50
# File 'lib/rom/factory/tuple_evaluator.rb', line 45

def initialize(attributes, relation, traits = {})
  @attributes = attributes
  @relation = relation.with(auto_struct: true)
  @traits = traits
  @sequence = Sequences[relation]
end

Instance Attribute Details

#attributesObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


33
34
35
# File 'lib/rom/factory/tuple_evaluator.rb', line 33

def attributes
  @attributes
end

#relationObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


36
37
38
# File 'lib/rom/factory/tuple_evaluator.rb', line 36

def relation
  @relation
end

#sequenceObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


42
43
44
# File 'lib/rom/factory/tuple_evaluator.rb', line 42

def sequence
  @sequence
end

#traitsObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


39
40
41
# File 'lib/rom/factory/tuple_evaluator.rb', line 39

def traits
  @traits
end

Instance Method Details

#assoc_names(traits = []) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

[View source]

117
118
119
# File 'lib/rom/factory/tuple_evaluator.rb', line 117

def assoc_names(traits = [])
  assocs(traits).map(&:name)
end

#assocs(traits_names = []) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

[View source]

121
122
123
124
125
126
127
128
129
130
131
# File 'lib/rom/factory/tuple_evaluator.rb', line 121

def assocs(traits_names = [])
  found_assocs = traits
    .values_at(*traits_names)
    .compact
    .map(&:associations).flat_map(&:elements)
    .inject(AttributeRegistry.new(attributes.associations.elements), :<<)

  exclude = traits_names.select { |t| t.is_a?(Hash) }.reduce(:merge) || EMPTY_HASH

  found_assocs.reject { |a| exclude[a.name] == false }
end

#build_assoc?(name, attributes) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)
[View source]

96
97
98
# File 'lib/rom/factory/tuple_evaluator.rb', line 96

def build_assoc?(name, attributes)
  attributes.key?(name) && attributes[name] != [] && !attributes[name].nil?
end

#build_assoc_attrs(key, fk, value) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

[View source]

100
101
102
103
104
105
106
# File 'lib/rom/factory/tuple_evaluator.rb', line 100

def build_assoc_attrs(key, fk, value)
  if value.is_a?(Array)
    value.map { |el| build_assoc_attrs(key, fk, el) }
  else
    {attributes[key].foreign_key => fk}.merge(value.to_h)
  end
end

#defaults(traits, attrs, **opts) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

[View source]

57
58
59
60
# File 'lib/rom/factory/tuple_evaluator.rb', line 57

def defaults(traits, attrs, **opts)
  mergeable_attrs = select_mergeable_attrs(traits, attrs)
  evaluate(traits, attrs, opts).merge(mergeable_attrs)
end

#has_associations?(traits = []) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)
[View source]

134
135
136
# File 'lib/rom/factory/tuple_evaluator.rb', line 134

def has_associations?(traits = [])
  !assoc_names(traits).empty?
end

#model(traits, combine: assoc_names(traits)) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

[View source]

52
53
54
# File 'lib/rom/factory/tuple_evaluator.rb', line 52

def model(traits, combine: assoc_names(traits))
  @relation.combine(*combine).mapper.model
end

#persist_associations(tuple, parent, traits = []) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

[View source]

109
110
111
112
113
114
# File 'lib/rom/factory/tuple_evaluator.rb', line 109

def persist_associations(tuple, parent, traits = [])
  assoc_names(traits).each do |name|
    assoc = tuple[name]
    assoc.call(parent, persist: true) if assoc.is_a?(Proc)
  end
end

#primary_keyObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

[View source]

139
140
141
# File 'lib/rom/factory/tuple_evaluator.rb', line 139

def primary_key
  relation.primary_key
end

#struct(*traits, **attrs) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

[View source]

63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/rom/factory/tuple_evaluator.rb', line 63

def struct(*traits, **attrs)
  merged_attrs = struct_attrs.merge(defaults(traits, attrs, persist: false))
  is_callable = proc { |_name, value| value.respond_to?(:call) }

  callables = merged_attrs.select(&is_callable)
  attributes = merged_attrs.reject(&is_callable)

  materialized_callables = {}
  callables.each_value do |callable|
    materialized_callables.merge!(callable.call(attributes, persist: false))
  end

  attributes.merge!(materialized_callables)

  assoc_attrs = attributes.slice(*assoc_names(traits)).merge(
    assoc_names(traits)
      .select { |key|
        build_assoc?(key, attributes)
      }
      .map { |key|
        [key, build_assoc_attrs(key, attributes[relation.primary_key], attributes[key])]
      }
    .to_h
  )

  model_attrs = relation.output_schema[attributes]
  model_attrs.update(assoc_attrs)

  model(traits).new(**model_attrs)
rescue StandardError => e
  raise TupleEvaluatorError.new(relation, e, attrs, traits, assoc_attrs)
end