class ROM::Factory::TupleEvaluator

@api private

Attributes

attributes[R]

@api private

model[R]

@api private

relation[R]

@api private

sequence[R]

@api private

traits[R]

@api private

Public Class Methods

new(attributes, relation, traits = {}) click to toggle source

@api private

# File lib/rom/factory/tuple_evaluator.rb, line 25
def initialize(attributes, relation, traits = {})
  @attributes = attributes
  @relation = relation.with(auto_struct: true)
  @traits = traits
  @model = @relation.combine(*assoc_names).mapper.model
  @sequence = Sequences[relation]
end

Public Instance Methods

assoc_names(traits = []) click to toggle source

@api private

# File lib/rom/factory/tuple_evaluator.rb, line 74
def assoc_names(traits = [])
  assocs(traits).map(&:name)
end
assocs(traits_names = []) click to toggle source
# File lib/rom/factory/tuple_evaluator.rb, line 78
def assocs(traits_names = [])
  traits
    .values_at(*traits_names)
    .map(&:associations).flat_map(&:elements)
    .inject(AttributeRegistry.new(attributes.associations.elements), :<<)
end
defaults(traits, attrs, opts = EMPTY_HASH) click to toggle source

@api private

# File lib/rom/factory/tuple_evaluator.rb, line 34
def defaults(traits, attrs, opts = EMPTY_HASH)
  evaluate(traits, attrs, opts).merge(attrs)
end
extract_tuple(args) click to toggle source

@api private

# File lib/rom/factory/tuple_evaluator.rb, line 96
def extract_tuple(args)
  if !args.empty? && args.last.is_a?(::Hash)
    *traits, attrs = args

    [traits, attrs]
  else
    [args, EMPTY_HASH]
  end
end
has_associations?(traits = []) click to toggle source

@api private

# File lib/rom/factory/tuple_evaluator.rb, line 86
def has_associations?(traits = [])
  !assoc_names(traits).empty?
end
persist_associations(tuple, parent, traits = []) click to toggle source

@api private

# File lib/rom/factory/tuple_evaluator.rb, line 66
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_key() click to toggle source

@api private

# File lib/rom/factory/tuple_evaluator.rb, line 91
def primary_key
  relation.primary_key
end
struct(*args) click to toggle source

@api private

# File lib/rom/factory/tuple_evaluator.rb, line 39
def struct(*args)
  traits, attrs = extract_tuple(args)
  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 do |_name, callable|
    materialized_callables.merge!(callable.call(attributes, persist: false))
  end

  attributes.merge!(materialized_callables)

  associations = assoc_names
    .map { |key| [key, attributes[key]] if attributes.key?(key) }
    .compact
    .to_h

  attributes = relation.output_schema[attributes]
  attributes.update(associations)

  model.new(attributes)
end

Private Instance Methods

evaluate(traits, attrs, opts) click to toggle source

@api private

# File lib/rom/factory/tuple_evaluator.rb, line 109
def evaluate(traits, attrs, opts)
  evaluate_values(attrs, opts)
    .merge(evaluate_associations(attrs, opts))
    .merge(evaluate_traits(traits, attrs, opts))
end
evaluate_associations(attrs, opts) click to toggle source

@api private

# File lib/rom/factory/tuple_evaluator.rb, line 136
def evaluate_associations(attrs, opts)
  attributes.associations.each_with_object({}) do |assoc, h|
    if assoc.dependency?(relation)
      h[assoc.name] = ->(parent, call_opts) do
        assoc.call(parent, **opts, **call_opts)
      end
    else
      result = assoc.(attrs, **opts)
      h.update(result) if result
    end
  end
end
evaluate_traits(traits, attrs, opts) click to toggle source
# File lib/rom/factory/tuple_evaluator.rb, line 127
def evaluate_traits(traits, attrs, opts)
  return {} if traits.empty?

  traits_attrs = self.traits.values_at(*traits).flat_map(&:elements)
  registry = AttributeRegistry.new(traits_attrs)
  self.class.new(registry, relation).defaults([], attrs, opts)
end
evaluate_values(attrs, opts) click to toggle source

@api private

# File lib/rom/factory/tuple_evaluator.rb, line 116
def evaluate_values(attrs, opts)
  attributes.values.tsort.each_with_object({}) do |attr, h|
    deps = attr.dependency_names.map { |k| h[k] }.compact
    result = attr.(attrs, *deps)

    if result
      h.update(result)
    end
  end
end
next_id() click to toggle source

@api private

# File lib/rom/factory/tuple_evaluator.rb, line 163
def next_id
  sequence.()
end
struct_attrs() click to toggle source

@api private

# File lib/rom/factory/tuple_evaluator.rb, line 150
def struct_attrs
  struct_attrs = relation.schema.
    reject(&:primary_key?).
    map { |attr| [attr.name, nil] }.to_h

  if primary_key
    struct_attrs.merge(primary_key => next_id)
  else
    struct_attrs
  end
end