Class: Karafka::Web::Ui::Lib::Sorter

Inherits:
Object
  • Object
show all
Defined in:
lib/karafka/web/ui/lib/sorter.rb

Overview

Note:

It handles sorting in place by mutating appropriate resources and sub-components

Sorting engine for deep in-memory structures It supports hashes, arrays and hash proxies.

Instance Method Summary collapse

Constructor Details

#initialize(sort_query, allowed_attributes:) ⇒ Sorter

Returns a new instance of Sorter.

Parameters:

  • sort_query (String)

    query for sorting or empty string if no sorting needed

  • allowed_attributes (Array<String>)

    attributes on which we allow to sort. Since we can sort on method invocations, this needs to be limited and provided on a per controller basis.



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/karafka/web/ui/lib/sorter.rb', line 24

def initialize(sort_query, allowed_attributes:)
  field, order = sort_query.split(' ')

  @order = order.to_s.downcase
  @order = ALLOWED_ORDERS.first unless ALLOWED_ORDERS.include?(@order)

  # Normalize the key since we do not operate on capitalized values
  @field = field.to_s.downcase

  @field = '' unless allowed_attributes.include?(@field)

  # Things we have already seen and sorted. Prevents crashing on the circular
  # dependencies sorting when same resources are present in different parts of the tree
  @seen = {}
end

Instance Method Details

#call(resource, current_depth = 0) ⇒ Object

Sorts the structure and returns it sorted.

Parameters:

  • resource (Hash, Array, Lib::HashProxy)

    structure we want to sort

  • current_depth (defaults to: 0)

    []



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
# File 'lib/karafka/web/ui/lib/sorter.rb', line 44

def call(resource, current_depth = 0)
  # Skip if there is no sort field at all
  return resource if @field.empty?
  # Skip if we've already seen this resource
  # We use object id instead of full object as the objects can get big
  return resource if @seen.key?(resource.object_id)
  # Skip if we are too deep
  return resource if current_depth > MAX_DEPTH

  @seen[resource.object_id] = nil

  case resource
  when Array
    sort_array!(resource, current_depth)
  when Hash
    sort_hash!(resource, current_depth)
  when Lib::HashProxy
    # We can short hash in place here, because it will be still references (the same)
    # in the hash proxy object, so we can do it that way
    sort_hash!(resource.to_h, current_depth)
  when Enumerable
    sort_array!(resource, current_depth)
  end

  resource
end