Class: Kiba::Extend::Utils::Lookup::RowSorter

Inherits:
Object
  • Object
show all
Defined in:
lib/kiba/extend/utils/lookup/row_sorter.rb

Overview

Note:

This class is not a transform to sort the rows in a job. It was not designed or tested with more than a few rows in any given #call. It may be possible to leverage this to create a Sort::Rows transform in the future, but it would be subject to the same types of performance issues present with any of the “hold all rows in memory at the same time” transforms.

Sorts an array of rows on a given field, according to the given parameters

Currently this class can be used as an optional argument to Transforms::Merge::MultiRowLookup, if you need to ensure values from multiple looked-up rows are merged in a particular order.

Currently only supports sorting values as strings (the default) or as integers (passing as: :to_i). If you need to sort by dates, you must add a column to your lookup table that expresses the date as an integer. For simple/clean dates, something like this could work:

transform do |row|
  dateval = row[:datefield]
  row[:date_as_num] = Date.parse(dateval).jd
  row
end

Examples

Rows:

rows = [
  { id: '1' },
  { id: '10' },
  { id: '11' },
  { id: '100'},
  { id: nil },
  { id: '' },
  { id: 'XR3' },
  { id: '25' }
]

With defaults (asc, sorted as strings, blanks first)

sorter = Lookup::RowSorter.new(on: :id)
result = sorter.call(rows)
result.map{ |row| row[:id] } =>
  [nil, '', '1', '10', '100', '11', '25', 'XR3']

Asc, sorted as integers, blanks first

sorter = Lookup::RowSorter.new(on: :id, as: :to_i)
result = sorter.call(rows)
result.map{ |row| row[:id] } =>
  [nil, '', '1', '10', '11', '25', '100', 'XR3']

Asc, sorted as strings, blanks last

sorter = Lookup::RowSorter.new(on: :id, as: :to_i)
result = sorter.call(rows)
result.map{ |row| row[:id] } =>
  ['1', '10', '100', '11', '25', 'XR3', nil, '']

Desc, sorted as strings, blanks last

sorter = Lookup::RowSorter.new(on: :id, as: :to_i)
result = sorter.call(rows)
result.map{ |row| row[:id] } =>
  [nil, '', 'XR3', '25', '11', '100', '10', '1']

Since:

  • 2.8.0

Defined Under Namespace

Classes: MissingSortFieldError

Instance Method Summary collapse

Constructor Details

#initialize(on:, dir: :asc, as: nil, blanks: :first) ⇒ RowSorter

Returns a new instance of RowSorter.

Parameters:

  • on (Symbol)

    field on which to sort the rows

  • dir (:asc, :desc) (defaults to: :asc)

    sort direction

  • as (Symbol) (defaults to: nil)

    method to call in order to convert field values for sorting

  • blanks (:first, :last) (defaults to: :first)

    where to position blank values in the sorted list

Since:

  • 2.8.0



96
97
98
99
100
101
# File 'lib/kiba/extend/utils/lookup/row_sorter.rb', line 96

def initialize(on:, dir: :asc, as: nil, blanks: :first)
  @sortfield = on
  @sortdir = dir
  @sortas = as
  @blanks = blanks
end

Instance Method Details

#call(arr) ⇒ Object

Parameters:

  • arr (Array<Hash>)

    array of rows to sort

Since:

  • 2.8.0



104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/kiba/extend/utils/lookup/row_sorter.rb', line 104

def call(arr)
  fail MissingSortFieldError.new("Cannot sort on missing field: `#{sortfield}`") unless arr.first.key?(sortfield)

  blanks_sep = arr.group_by { |row| row[sortfield].blank? }

  blank = blanks_sep[true]
  not_blank = blanks_sep[false]

  sorted = sorted_nonblanks(not_blank)

  arranged = arrange_sorted_rows(sorted)

  add_blanks(arranged, blank)
end