Class: Gitlab::Pagination::Keyset::SimpleOrderBuilder

Inherits:
Object
  • Object
show all
Defined in:
lib/gitlab/pagination/keyset/simple_order_builder.rb

Overview

This class transforms the `order()` values from an Activerecord scope into a Gitlab::Pagination::Keyset::Order instance so the query later can be used in keyset pagination.

Return values:

transformed_scope, true

# true indicates that the new scope was successfully built

orginal_scope, false

# false indicates that the order values are not supported in this class

Constant Summary collapse

NULLS_ORDER_REGEX =
/(?<column_name>.*) (?<direction>\bASC\b|\bDESC\b) (?<nullable>\bNULLS LAST\b|\bNULLS FIRST\b)/.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(scope:) ⇒ SimpleOrderBuilder

Returns a new instance of SimpleOrderBuilder.


20
21
22
23
24
25
26
27
28
# File 'lib/gitlab/pagination/keyset/simple_order_builder.rb', line 20

def initialize(scope:)
  @scope = scope
  # We need to run 'compact' because 'nil' is not removed from order_values
  # in some cases due to the use of 'default_scope'.
  @order_values = scope.order_values.compact
  @model_class = scope.model
  @arel_table = @model_class.arel_table
  @primary_key = @model_class.primary_key
end

Class Method Details

.build(scope) ⇒ Object


16
17
18
# File 'lib/gitlab/pagination/keyset/simple_order_builder.rb', line 16

def self.build(scope)
  new(scope: scope).build
end

Instance Method Details

#buildObject


30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/gitlab/pagination/keyset/simple_order_builder.rb', line 30

def build
  order = if order_values.empty?
            primary_key_descending_order
          elsif Gitlab::Pagination::Keyset::Order.keyset_aware?(scope)
            Gitlab::Pagination::Keyset::Order.extract_keyset_order_object(scope)
          # Ordered by a primary key. Ex. 'ORDER BY id'.
          elsif ordered_by_primary_key?
            primary_key_order
          # Ordered by one non-primary table column. Ex. 'ORDER BY created_at'.
          elsif ordered_by_other_column?
            column_with_tie_breaker_order
          # Ordered by two table columns with the last column as a tie breaker. Ex. 'ORDER BY created, id ASC'.
          elsif ordered_by_other_column_with_tie_breaker?
            tie_breaker_attribute = order_values.second

            tie_breaker_column_order = Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
              attribute_name: model_class.primary_key,
              order_expression: tie_breaker_attribute
            )

            column_with_tie_breaker_order(tie_breaker_column_order)
          end

  order ? [scope.reorder!(order), true] : [scope, false] # [scope, success]
end