class ROM::Relation::Combined

Represents a relation graphs which combines root relation with other relation nodes

@api public

Public Class Methods

new(relation, nodes) click to toggle source

Create a new relation combined with others

@param [Relation] relation @param [Array<Relation>] nodes

@return [Combined]

@api public

Calls superclass method
# File lib/rom/relation/combined.rb, line 23
def self.new(relation, nodes)
  struct_ns = relation.options[:struct_namespace]
  new_nodes = nodes.uniq(&:name).map { |node| node.struct_namespace(struct_ns) }

  root =
    if relation.is_a?(self)
      new_nodes.concat(relation.nodes)
      relation.root
    else
      relation
    end

  super(root, new_nodes)
end

Public Instance Methods

call(*args) click to toggle source

Materialize combined relation

@return [Loaded]

@api public

# File lib/rom/relation/combined.rb, line 65
def call(*args)
  left = root.with(auto_map: false, auto_struct: false).call(*args)

  right =
    if left.empty?
      nodes.map { |node| Loaded.new(node, EMPTY_ARRAY) }
    else
      nodes.map { |node| node.call(left) }
    end

  if auto_map?
    Loaded.new(self, mapper.([left, right]))
  else
    Loaded.new(self, [left, right])
  end
end
combine(*args) click to toggle source

Combine with other relations

@see Relation#combine

@return [Combined]

@api public

# File lib/rom/relation/combined.rb, line 56
def combine(*args)
  self.class.new(root, nodes + root.combine(*args).nodes)
end
combine_with(*others) click to toggle source

Combine this graph with more nodes

@param [Array<Relation>] others A list of relations

@return [Graph]

@api public

# File lib/rom/relation/combined.rb, line 45
def combine_with(*others)
  self.class.new(root, nodes + others)
end
command(type, *args) click to toggle source

Return a `:create` command that can insert data from a nested hash.

This is limited to `:create` commands only, because automatic restriction for `:update` commands would be quite complex. It's possible that in the future support for `:update` commands will be added though.

Another limitation is that it can only work when you're composing parent and its child(ren), which follows canonical hierarchy from your database, so that parents are created first, then their PKs are set as FKs in child tuples. It should be possible to make it work with both directions (parent => child or child => parent), and it would require converting input tuples based on how they depend on each other, which we could do in the future.

Expanding functionality of this method is planned for rom 5.0.

@see Relation#command

@raise NotImplementedError when type is not `:create`

@api public

Calls superclass method ROM::Relation::Commands#command
# File lib/rom/relation/combined.rb, line 143
def command(type, *args)
  if type == :create
    super
  else
    raise NotImplementedError, "#{self.class}#command doesn't work with #{type.inspect} command type yet"
  end
end
node(name) { |node| ... } click to toggle source

Return a new combined relation with adjusted node returned from a block

@example with a node identifier

combine(:tasks).node(:tasks) { |tasks| tasks.prioritized }

@example with a nested path

combine(tasks: :tags).node(tasks: :tags) { |tags| tags.where(name: 'red') }

@param [Symbol] name The node relation name

@yieldparam [Relation] relation The relation node @yieldreturn [Relation] The new relation node

@return [Relation]

@api public

# File lib/rom/relation/combined.rb, line 98
def node(name, &block)
  if name.is_a?(Symbol) && !nodes.map { |n| n.name.key }.include?(name)
    raise ArgumentError, "#{name.inspect} is not a valid aggregate node name"
  end

  new_nodes = nodes.map { |node|
    case name
    when Symbol
      name == node.name.key ? yield(node) : node
    when Hash
      other, *rest = name.flatten(1)
      if other == node.name.key
        nodes.detect { |n| n.name.key == other }.node(*rest, &block)
      else
        node
      end
    else
      node
    end
  }

  with_nodes(new_nodes)
end

Private Instance Methods

decorate?(other) click to toggle source

@api private

Calls superclass method
# File lib/rom/relation/combined.rb, line 154
def decorate?(other)
  super || other.is_a?(self.class) || other.is_a?(Wrap)
end