Module: Miscellany::SortLang

Defined in:
lib/miscellany/sort_lang.rb

Defined Under Namespace

Classes: Parser

Class Method Summary collapse

Class Method Details

.distinct_sorts(sorts) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/miscellany/sort_lang.rb', line 25

def self.distinct_sorts(sorts)
  seen_sorts = Set.new

  # Only include each sort key/"column" once
  sorts.select do |sort|
    sid = sort[:key] || sort[:column]
    next true unless sid.present?

    if seen_sorts.include?(sid)
      false
    else
      seen_sorts << sid
      true
    end
  end
end

.normalize_sort(sort, key: nil) ⇒ Object

Normalized Format:

key: string,
column: string,
order: 'DESC' | 'ASC',
force_order?: boolean, # Prevent overriding order
nulls?: 'high' | 'low' | 'first' | 'last',



11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/miscellany/sort_lang.rb', line 11

def self.normalize_sort(sort, key: nil)
  sort = sort.to_s if sort.is_a?(Symbol)
  if sort.is_a?(Array)
    sort = { **normalize_sort(sort[0]), **(sort[1] || {}) }
  elsif sort.is_a?(String)
    m = sort.match(/^([\w\.]+)(?: (ASC|DESC)(!?))?$/)
    sort = { column: m[1], order: m[2], force_order: m[3].present? }.compact
  elsif sort.is_a?(Proc)
    sort = { column: sort }
  end
  sort[:key] = key || sort[:column]
  sort.compact
end

.sqlize(sorts) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/miscellany/sort_lang.rb', line 42

def self.sqlize(sorts)
  sorts.map do |sort|
    order = sort[:order] || 'ASC'
    if sort[:column].is_a?(Proc)
      sort[:column].call(order)
    else
      desired_nulls = (sort[:nulls] || :low).to_s.downcase.to_sym
      nulls = case desired_nulls
      when :last
        'LAST'
      when :first
        'FIRST'
      else
        (desired_nulls == :high) == (order.to_s.upcase == 'DESC') ? 'FIRST' : 'LAST'
      end
      "#{sort[:column]} #{order} NULLS #{nulls}"
    end
  end.join(', ')
end