# File lib/params_ready/pagination/keyset_pagination.rb, line 162 def primary_keys_arel(ordering, arel_table, context) columns = cursor_columns.lazy.select do |name| ordering.definition.primary_keys.member? name end cursor_columns_arel(ordering, arel_table, context, columns: columns).force end
class ParamsReady::Pagination::KeysetPagination
Public Instance Methods
after_page_value(keyset)
click to toggle source
# File lib/params_ready/pagination/keyset_pagination.rb, line 130 def after_page_value(keyset) keyset ||= {} { limit: limit, direction: :aft, keyset: keyset } end
before_page_value(keyset)
click to toggle source
# File lib/params_ready/pagination/keyset_pagination.rb, line 125 def before_page_value(keyset) keyset ||= {} { limit: limit, direction: :bfr, keyset: keyset } end
cursor()
click to toggle source
# File lib/params_ready/pagination/keyset_pagination.rb, line 170 def cursor return nil unless is_definite? keyset = self[:keyset] keyset.names.keys.map do |column_name| keyset[column_name].unwrap end end
cursor_columns()
click to toggle source
# File lib/params_ready/pagination/keyset_pagination.rb, line 151 def cursor_columns self[:keyset].names.keys end
cursor_columns_arel(ordering, arel_table, context, columns: cursor_columns)
click to toggle source
# File lib/params_ready/pagination/keyset_pagination.rb, line 155 def cursor_columns_arel(ordering, arel_table, context, columns: cursor_columns) columns.map do |name| column = ordering.definition.columns[name] column.attribute(name, arel_table, context) end end
cursor_predicates(direction, keyset, ordering, arel_table, context)
click to toggle source
# File lib/params_ready/pagination/keyset_pagination.rb, line 112 def cursor_predicates(direction, keyset, ordering, arel_table, context) direction = Direction.instance(direction) direction.cursor_predicates(keyset, ordering, arel_table, context) end
direction()
click to toggle source
# File lib/params_ready/pagination/keyset_pagination.rb, line 143 def direction self[:direction].unwrap end
exists_predicate(subselect, ordering, arel_table)
click to toggle source
# File lib/params_ready/pagination/keyset_pagination.rb, line 70 def exists_predicate(subselect, ordering, arel_table) table_alias = self.table_alias(arel_table) aliased = arel_table.alias(table_alias) select_manager = Arel::SelectManager.new.from(subselect.as(table_alias)) related = related_clause(arel_table, aliased, ordering.definition.primary_keys) select_manager.where(related).project('1').exists end
first_page_value()
click to toggle source
# File lib/params_ready/pagination/keyset_pagination.rb, line 117 def first_page_value { limit: limit, direction: :aft, keyset: {} } end
keyset()
click to toggle source
# File lib/params_ready/pagination/keyset_pagination.rb, line 147 def keyset self[:keyset].unwrap end
keyset_query(query, limit, direction, keyset, ordering, arel_table, context)
click to toggle source
# File lib/params_ready/pagination/keyset_pagination.rb, line 17 def keyset_query(query, limit, direction, keyset, ordering, arel_table, context) cursor, grouping = cursor_predicates(direction, keyset, ordering, arel_table, context) cte = cursor.cte_for_query(query, arel_table) unless cursor.nil? query = query.where(grouping) unless grouping.nil? query = query.with(cte) unless cte.nil? ordered = query.order(ordering_arel(direction, ordering, arel_table, context)) ordered.take(limit) end
keysets_for_relation(relation, limit, direction, keyset, ordering, context)
click to toggle source
# File lib/params_ready/pagination/keyset_pagination.rb, line 27 def keysets_for_relation(relation, limit, direction, keyset, ordering, context) arel_table = relation.arel_table cursor, predicates = cursor_predicates(direction, keyset, ordering, arel_table, context) full_query = relation.where(predicates) .reorder(ordering_arel(direction, ordering, arel_table, context)) .limit(limit) .select(*cursor_columns_arel(ordering, arel_table, context)) full_query = Arel::Nodes::SqlLiteral.new(full_query.to_sql) with_cte(relation, full_query, cursor) end
last_page_value()
click to toggle source
# File lib/params_ready/pagination/keyset_pagination.rb, line 121 def last_page_value { limit: limit, direction: :bfr, keyset: {} } end
limit()
click to toggle source
# File lib/params_ready/pagination/keyset_pagination.rb, line 135 def limit self[:limit].unwrap end
limit_key()
click to toggle source
# File lib/params_ready/pagination/keyset_pagination.rb, line 139 def limit_key :limit end
ordering_arel(direction, ordering, arel_table, context)
click to toggle source
# File lib/params_ready/pagination/keyset_pagination.rb, line 107 def ordering_arel(direction, ordering, arel_table, context) inverted = Direction.instance(direction).invert_ordering? ordering.to_arel(arel_table, context: context, inverted: inverted) end
paginate_query(query, ordering, arel_table, context)
click to toggle source
# File lib/params_ready/pagination/keyset_pagination.rb, line 55 def paginate_query(query, ordering, arel_table, context) cursor, predicates = cursor_predicates(direction, keyset, ordering, arel_table, context) cte = cursor.cte_for_query(query, arel_table) unless cursor.nil? subquery = query.deep_dup subquery = subquery.where(predicates) unless predicates.nil? subquery = subquery.with(cte) unless cte.nil? subselect = subquery.order(ordering_arel(direction, ordering, arel_table, context)) .take(limit) .project(primary_keys_arel(ordering, arel_table, context)) exists = exists_predicate(subselect, ordering, arel_table) query.where(exists) end
paginate_relation(relation, ordering, context)
click to toggle source
# File lib/params_ready/pagination/keyset_pagination.rb, line 39 def paginate_relation(relation, ordering, context) arel_table = relation.arel_table cursor, predicates = cursor_predicates(direction, keyset, ordering, arel_table, context) subselect = relation.where(predicates) .reorder(ordering_arel(direction, ordering, arel_table, context)) .limit(limit) .select(primary_keys_arel(ordering, arel_table, context)) subselect_sql = Arel::Nodes::SqlLiteral.new(subselect.to_sql) subselect_sql = with_cte_grouped(relation, subselect_sql, cursor) exists = exists_predicate(subselect_sql, ordering, arel_table) relation.where(exists) end
primary_keys_arel(ordering, arel_table, context)
click to toggle source
select_keysets(query, limit, direction, keyset, ordering, arel_table, context)
click to toggle source
# File lib/params_ready/pagination/keyset_pagination.rb, line 12 def select_keysets(query, limit, direction, keyset, ordering, arel_table, context) query = keyset_query(query, limit, direction, keyset, ordering, arel_table, context) query.project(*cursor_columns_arel(ordering, arel_table, context)) end
table_alias(arel_table)
click to toggle source
# File lib/params_ready/pagination/keyset_pagination.rb, line 103 def table_alias(arel_table) Helpers::ArelBuilder.safe_name "#{arel_table.name}_#{cursor_columns.join('_')}" end
with_cte(relation, select, cursor)
click to toggle source
# File lib/params_ready/pagination/keyset_pagination.rb, line 94 def with_cte(relation, select, cursor) return select if cursor.nil? cte = cursor.cte_for_relation(relation) return select if cte.nil? Arel::Nodes::SqlLiteral.new([cte.to_sql, select].join(' ')) end
with_cte_grouped(relation, select, cursor)
click to toggle source
# File lib/params_ready/pagination/keyset_pagination.rb, line 89 def with_cte_grouped(relation, select, cursor) with_cte = with_cte(relation, select, cursor) Arel::Nodes::Grouping.new(with_cte) end