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

original_scope, false

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

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(scope:) ⇒ SimpleOrderBuilder

Returns a new instance of SimpleOrderBuilder.



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/gitlab/pagination/keyset/simple_order_builder.rb', line 18

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
  @order_value_names = extract_order_value_names
  @model_class = scope.model
  @arel_table = @model_class.arel_table
  # Support cases where a single logical primary key has been specified, but also cases where there is a true
  # composite primary key
  @primary_keys = if @model_class.primary_key.nil?
                    @model_class.connection.primary_keys(@model_class.table_name)
                  else
                    Array.wrap(@model_class.primary_key)
                  end

  @primary_keys = @primary_keys.map(&:to_s)
end

Class Method Details

.build(scope) ⇒ Object



14
15
16
# File 'lib/gitlab/pagination/keyset/simple_order_builder.rb', line 14

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

Instance Method Details

#buildObject



65
66
67
68
# File 'lib/gitlab/pagination/keyset/simple_order_builder.rb', line 65

def build
  keyset_order, success = build_order
  success ? [scope.reorder!(keyset_order), success] : [scope, false]
end

#build_orderObject



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/gitlab/pagination/keyset/simple_order_builder.rb', line 37

def build_order
  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
          elsif ordered_by_primary_key_prefix?
            primary_key_order_from_prefix
          # Ordered by one non-primary table column. Ex. 'ORDER BY created_at'.
          elsif ordered_by_other_columns?
            columns_with_tie_breaker_order(order_values)
          # Ordered by two table columns with the last column as a tie breaker. Ex. 'ORDER BY created, id ASC'.
          elsif ordered_by_other_columns_with_tie_breaker?
            tie_breaker_attribute = order_values.last

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

            columns_with_tie_breaker_order(order_values[0...-1], tie_breaker_column_order)
          end

  order ? [order, true] : [nil, false]
end