Class: ROM::Relation::Combined
- Includes:
- Commands
- Defined in:
- core/lib/rom/relation/combined.rb
Overview
Represents a relation graphs which combines root relation with other relation nodes
Instance Attribute Summary collapse
- #__memoized__ ⇒ Object included from Memoizable readonly private
Class Method Summary collapse
-
.new(relation, nodes) ⇒ Combined
Create a new relation combined with others.
Instance Method Summary collapse
-
#call(*args) ⇒ Loaded
Materialize combined relation.
-
#combine(*args) ⇒ Combined
Combine with other relations.
-
#combine_with(*others) ⇒ Graph
Combine this graph with more nodes.
-
#command(type, *args) ⇒ Object
Return a
:create
command that can insert data from a nested hash. -
#node(name) {|relation| ... } ⇒ Relation
Return a new combined relation with adjusted node returned from a block.
Dynamic Method Handling
This class handles dynamic methods through the method_missing method in the class ROM::Pipeline::Proxy
Instance Attribute Details
#__memoized__ ⇒ Object (readonly) Originally defined in module Memoizable
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.
Class Method Details
.new(relation, nodes) ⇒ Combined
Create a new relation combined with others
23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'core/lib/rom/relation/combined.rb', line 23 def self.new(relation, nodes) struct_ns = relation.[: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 |
Instance Method Details
#call(*args) ⇒ Loaded
Materialize combined relation
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'core/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) ⇒ Combined
Combine with other relations
56 57 58 |
# File 'core/lib/rom/relation/combined.rb', line 56 def combine(*args) self.class.new(root, nodes + root.combine(*args).nodes) end |
#combine_with(*others) ⇒ Graph
Combine this graph with more nodes
45 46 47 |
# File 'core/lib/rom/relation/combined.rb', line 45 def combine_with(*others) self.class.new(root, nodes + others) end |
#command(type, *args) ⇒ Object
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.
143 144 145 146 147 148 149 |
# File 'core/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) {|relation| ... } ⇒ Relation
Return a new combined relation with adjusted node returned from a block
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'core/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 |