Class: OccamsRecord::Merge
- Inherits:
-
Object
- Object
- OccamsRecord::Merge
- Defined in:
- lib/occams-record/merge.rb
Overview
Represents a merge operation to be performed. Merges are always “left” merges. You initialize the Merge with the “left” records, and the name of the attribute into which “right” records will be placed.
After initializing, perform a specific type of merge by calling the appropriate *! method.
Instance Attribute Summary collapse
-
#target_rows ⇒ Array<OccamsRecord::Results::Row>
readonly
The rows into which associated rows will be merged.
Instance Method Summary collapse
-
#initialize(target_rows, assoc_attr) ⇒ Merge
constructor
Initialize a new Merge operation.
-
#many!(assoc_rows, mapping) ⇒ Object
Merge an array of assoc_rows into the target_rows.
-
#single!(assoc_rows, mapping) ⇒ Object
Merge a single assoc_row into each target_rows (or nil if one can’t be found).
Constructor Details
#initialize(target_rows, assoc_attr) ⇒ Merge
Initialize a new Merge operation.
18 19 20 21 |
# File 'lib/occams-record/merge.rb', line 18 def initialize(target_rows, assoc_attr) @target_rows = target_rows @assign = "#{assoc_attr}=" end |
Instance Attribute Details
#target_rows ⇒ Array<OccamsRecord::Results::Row> (readonly)
Returns the rows into which associated rows will be merged.
10 11 12 |
# File 'lib/occams-record/merge.rb', line 10 def target_rows @target_rows end |
Instance Method Details
#many!(assoc_rows, mapping) ⇒ Object
Merge an array of assoc_rows into the target_rows. Some target_rows may end up with 0 matching associations, and they’ll be assigned empty arrays.
for the associated rows.
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/occams-record/merge.rb', line 88 def many!(assoc_rows, mapping) target_attrs = mapping.keys assoc_attrs = mapping.values # Optimized for merges where there's a single mapping key pair (which is the vast majority) if mapping.size == 1 target_attr, assoc_attr = target_attrs[0], assoc_attrs[0] begin assoc_rows_by_attr = assoc_rows.group_by { |r| r.send assoc_attr } rescue NoMethodError => e raise MissingColumnError.new(assoc_rows[0], e.name) end target_rows.each do |row| begin pkey = row.send target_attr rescue NoMethodError => e raise MissingColumnError.new(row, e.name) end row.send(@assign, assoc_rows_by_attr[pkey] || []) end # Slower but works with any number of mapping key pairs else begin assoc_rows_by_attrs = assoc_rows.group_by { |r| assoc_attrs.map { |attr| r.send attr } } rescue NoMethodError => e raise MissingColumnError.new(assoc_rows[0], e.name) end target_rows.each do |row| begin pkeys = target_attrs.map { |attr| row.send attr } rescue NoMethodError => e raise MissingColumnError.new(row, e.name) end row.send(@assign, assoc_rows_by_attrs[pkeys] || []) end end nil end |
#single!(assoc_rows, mapping) ⇒ Object
Merge a single assoc_row into each target_rows (or nil if one can’t be found). target_attr and assoc_attr are the matching keys on target_rows and assoc_rows, respectively.
for the associated rows.
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/occams-record/merge.rb', line 31 def single!(assoc_rows, mapping) target_attrs = mapping.keys assoc_attrs = mapping.values # Optimized for merges where there's a single mapping key pair (which is the vast majority) if mapping.size == 1 target_attr, assoc_attr = target_attrs[0], assoc_attrs[0] assoc_rows_by_ids = assoc_rows.each_with_object({}) { |assoc_row, acc| begin id = assoc_row.send assoc_attr rescue NoMethodError => e raise MissingColumnError.new(assoc_row, e.name) end acc[id] ||= assoc_row } target_rows.each do |row| begin attr = row.send target_attr rescue NoMethodError => e raise MissingColumnError.new(row, e.name) end row.send(@assign, attr ? assoc_rows_by_ids[attr] : nil) end # Slower but works with any number of mapping key pairs else assoc_rows_by_ids = assoc_rows.each_with_object({}) { |assoc_row, acc| begin ids = assoc_attrs.map { |attr| assoc_row.send attr } rescue NoMethodError => e raise MissingColumnError.new(assoc_row, e.name) end acc[ids] ||= assoc_row } target_rows.each do |row| begin attrs = target_attrs.map { |attr| row.send attr } rescue NoMethodError => e raise MissingColumnError.new(row, e.name) end row.send(@assign, attrs.any? ? assoc_rows_by_ids[attrs] : nil) end end nil end |