Module: ROM::Repository::LoadingProxy::Combine

Included in:
ROM::Repository::LoadingProxy
Defined in:
lib/rom/repository/loading_proxy/combine.rb

Overview

Provides convenient methods for producing combined relations

Instance Method Summary collapse

Instance Method Details

#combine(options) ⇒ LoadingProxy

Combine with other relations

Examples:

# combining many
users.combine(many: { tasks: [tasks, id: :task_id] })
users.combine(many: { tasks: [tasks.for_users, id: :task_id] })

# combining one
users.combine(one: { task: [tasks, id: :task_id] })

Parameters:

  • options (Hash)

Returns:



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/rom/repository/loading_proxy/combine.rb', line 23

def combine(options)
  combine_opts = options.each_with_object({}) do |(type, relations), result|
    result[type] = relations.each_with_object({}) do |(name, (other, keys)), h|
      h[name] = [
        other.curried? ? other : other.combine_method(relation, keys), keys
      ]
    end
  end

  nodes = combine_opts.flat_map do |type, relations|
    relations.map { |name, (relation, keys)|
      relation.combined(name, keys, type)
    }
  end

  __new__(relation.combine(*nodes))
end

#combine_children(options) ⇒ LoadingProxy

Shortcut for combining with children which infers the join keys

Examples:

users.combine_parents(many: tasks)

Parameters:

  • options (Hash)

Returns:



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/rom/repository/loading_proxy/combine.rb', line 79

def combine_children(options)
  combine(options.each_with_object({}) { |(type, children), h|
    h[type] =
      if children.is_a?(Hash)
        children.each_with_object({}) { |(key, child), r|
          r[key] = [child, combine_keys(relation, :children)]
        }
      else
        (children.is_a?(Array) ? children : [children])
          .each_with_object({}) { |child, r|
          r[child.combine_tuple_key(type)] = [
            child, combine_keys(relation, :children)
          ]
        }
      end
  })
end

#combine_keys(relation, type) ⇒ Hash<Symbol=>Symbol>

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.

Infer join keys for a given relation and association type

Parameters:

  • relation (LoadingProxy)
  • type (Symbol)

    The type can be either :parent or :children

Returns:

  • (Hash<Symbol=>Symbol>)


105
106
107
108
109
110
111
# File 'lib/rom/repository/loading_proxy/combine.rb', line 105

def combine_keys(relation, type)
  if type == :parent
    { relation.foreign_key => relation.primary_key }
  else
    { relation.primary_key => relation.foreign_key }
  end
end

#combine_method(other, keys) ⇒ LoadingProxy

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.

Infer relation for combine operation

By default it uses ‘for_combine` which is implemented as SQL::Relation extension

Returns:



121
122
123
124
125
126
127
128
129
# File 'lib/rom/repository/loading_proxy/combine.rb', line 121

def combine_method(other, keys)
  custom_name = :"for_#{other.base_name}"

  if relation.respond_to?(custom_name)
    __send__(custom_name)
  else
    for_combine(keys)
  end
end

#combine_parents(options) ⇒ LoadingProxy

Shortcut for combining with parents which infers the join keys

Examples:

tasks.combine_parents(one: users)

Parameters:

  • options (Hash)

Returns:



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/rom/repository/loading_proxy/combine.rb', line 51

def combine_parents(options)
  combine(options.each_with_object({}) { |(type, parents), h|
    h[type] =
      if parents.is_a?(Hash)
        parents.each_with_object({}) { |(key, parent), r|
          r[key] = [parent, combine_keys(parent, :parent)]
        }
      else
        (parents.is_a?(Array) ? parents : [parents])
          .each_with_object({}) { |parent, r|
          r[parent.combine_tuple_key(type)] = [
            parent, combine_keys(parent, :parent)
          ]
        }
      end
  })
end

#combine_tuple_key(arity) ⇒ Symbol

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.

Infer key under which a combine relation will be loaded

Returns:

  • (Symbol)


136
137
138
139
140
141
142
# File 'lib/rom/repository/loading_proxy/combine.rb', line 136

def combine_tuple_key(arity)
  if arity == :one
    Inflector.singularize(base_name).to_sym
  else
    base_name
  end
end

#combined(name, keys, type) ⇒ LoadingProxy

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.

Return combine representation of a loading-proxy relation

This will carry meta info used to produce a correct AST from a relation so that correct mapper can be generated

Returns:



152
153
154
# File 'lib/rom/repository/loading_proxy/combine.rb', line 152

def combined(name, keys, type)
  with(name: name, meta: { keys: keys, combine_type: type })
end