class CursorPager::Page
The main class that coordinates the whole pagination.
Attributes
after[R]
before[R]
first_value[R]
last_value[R]
order_values[R]
relation[R]
Public Class Methods
new(relation, first: nil, last: nil, after: nil, before: nil)
click to toggle source
# File lib/cursor_pager/page.rb, line 14 def initialize(relation, first: nil, last: nil, after: nil, before: nil) @configuration = CursorPager.configuration @relation = relation @first_value = first @last_value = last @after = after @before = before @order_values = OrderValues.from_relation(relation) add_default_order verify_order_directions! end
Public Instance Methods
cursor_for(item)
click to toggle source
# File lib/cursor_pager/page.rb, line 69 def cursor_for(item) return if item.nil? encoder.encode(item.id.to_s) end
first()
click to toggle source
A capped `first` value. The underlying instance variable `first_value` doesn't have limits on it. If neither `first` nor `last` is given, but `default_page_size` or `maximum_page_size` are configured, they will be used for first.
# File lib/cursor_pager/page.rb, line 31 def first @first ||= begin capped = limit_pagination_argument(first_value) if capped.nil? && last.nil? capped = default_page_size || maximum_page_size end capped end end
first_cursor()
click to toggle source
# File lib/cursor_pager/page.rb, line 75 def first_cursor cursor_for(records.first) end
last()
click to toggle source
A capped `last` value. The underlying instance variable `last_value` doesn't have limits on it.
# File lib/cursor_pager/page.rb, line 45 def last @last ||= limit_pagination_argument(last_value) end
last_cursor()
click to toggle source
# File lib/cursor_pager/page.rb, line 79 def last_cursor cursor_for(records.last) end
next_page?()
click to toggle source
# File lib/cursor_pager/page.rb, line 59 def next_page? @next_page ||= if before_limit_value.present? true elsif first sliced_relation.offset(first).exists? else false end end
previous_page?()
click to toggle source
# File lib/cursor_pager/page.rb, line 49 def previous_page? @previous_page ||= if after_limit_value.present? true elsif last limited_relation.offset_value.to_i.positive? else false end end
records()
click to toggle source
# File lib/cursor_pager/page.rb, line 83 def records @records ||= limited_relation.to_a end
Private Instance Methods
add_default_order()
click to toggle source
# File lib/cursor_pager/page.rb, line 89 def add_default_order return if sufficiently_ordered? direction = order_values.direction || :asc @order_values << OrderValue.new(relation, relation.primary_key, direction) end
after_limit_value()
click to toggle source
# File lib/cursor_pager/page.rb, line 145 def after_limit_value @after_limit_value ||= after.present? && limit_value_for(after) end
before_limit_value()
click to toggle source
# File lib/cursor_pager/page.rb, line 141 def before_limit_value @before_limit_value ||= before.present? && limit_value_for(before) end
limit_item_for(cursor)
click to toggle source
# File lib/cursor_pager/page.rb, line 157 def limit_item_for(cursor) id = encoder.decode(cursor) selects = order_values.map(&:select_string) ordered_relation_copy = ordered_relation.dup ordered_relation_copy.preload_values = [] ordered_relation_copy.eager_load_values = [] ordered_relation_copy .unscope(:includes).where(id: id).select(selects).first end
limit_pagination_argument(argument)
click to toggle source
Used to cap `first` and `last` arguments. Returns `nil` if the argument is `nil`, otherwise a value between `0` and `maximum_page_size`.
# File lib/cursor_pager/page.rb, line 112 def limit_pagination_argument(argument) return if argument.nil? if argument.negative? argument = 0 elsif maximum_page_size && argument > maximum_page_size argument = maximum_page_size end argument end
limit_value_for(cursor)
click to toggle source
# File lib/cursor_pager/page.rb, line 149 def limit_value_for(cursor) item = limit_item_for(cursor) raise CursorNotFoundError, cursor if item.blank? order_values.map { |value| item[value.select_alias] } end
limited_relation()
click to toggle source
# File lib/cursor_pager/page.rb, line 124 def limited_relation @limited_relation ||= LimitRelation.new(sliced_relation, first, last).call end
ordered_relation()
click to toggle source
# File lib/cursor_pager/page.rb, line 137 def ordered_relation @ordered_relation ||= relation.reorder(order_values.order_string) end
sliced_relation()
click to toggle source
# File lib/cursor_pager/page.rb, line 128 def sliced_relation @sliced_relation ||= SliceRelation.new( ordered_relation, order_values, after_limit_value, before_limit_value ).call end
sufficiently_ordered?()
click to toggle source
# File lib/cursor_pager/page.rb, line 97 def sufficiently_ordered? order_values.present? && order_values.all? do |value| value.primary_key? || value.type == :datetime end end
verify_order_directions!()
click to toggle source
# File lib/cursor_pager/page.rb, line 103 def verify_order_directions! return if order_values.map(&:direction).uniq.size == 1 raise ConflictingOrdersError end