Builds rows keyed by new_columns out of rows keyed by old_columns.
When column_map is given, the new rows are laid out by the slot of each column in it, and columns it doesn’t have are given indexes after its last one (see ExtendedIndexes). Without one, every column is extra, so the new row is in the order of new_columns.
Methods
Class Public methods
new(initial_indexes, old_columns, new_columns = old_columns, column_map = EMPTY) Link
: (Hash[String, Integer] | ExtendedIndexes, Array, ?Array, ?(Hash[String, Integer] | ExtendedIndexes)) -> void
# File activemodel/lib/active_model/indexed_row.rb, line 211 def initialize(initial_indexes, old_columns, new_columns = old_columns, column_map = EMPTY) # Handle duplicate keys pairs = new_columns.zip(old_columns).to_h extra = nil last_slot = nil # [slot in the new row, index in the original row] slots = pairs.map do |new_column, old_column| unless slot = column_map[new_column] extra ||= {} last_slot ||= IndexedRow.max_slot(column_map) slot = extra[new_column] = (last_slot += 1) end [slot, initial_indexes.fetch(old_column)] end slots.sort_by!(&:first) @new_indexes = if extra.nil? column_map elsif column_map.empty? extra.freeze else ExtendedIndexes.new(column_map, extra.freeze) end # If the new row has no gaps, it can be built with a single # values_at. Otherwise fill in an unset row by position. if slots.each_with_index.all? { |(slot, _), i| slot == i } @indexes_to_extract = slots.map(&:last) @slots = nil else @slots = slots @width = slots.last.first + 1 end end
Instance Public methods
build(original_row) Link
: (IndexedRow) -> IndexedRow
# File activemodel/lib/active_model/indexed_row.rb, line 250 def build(original_row) values = original_row.row if @slots row = IndexedRow.unset_row(@width) @slots.each { |slot, index| row[slot] = values[index] } else row = values.values_at(*@indexes_to_extract) end IndexedRow.new(@new_indexes, row.freeze) end