module Praxis::Extensions::Pagination

Constants

PaginationStruct

This PaginatedController concern should be added to controllers that have actions that define the pagination and order parameters so that one can call the domain model to craft the query ‘domain_model.craft_pagination_query(base_query, pagination: _pagination)` This will handle all the required logic for paginating, ordering and generating the Link and TotalCount headers.

Here’s a simple example on how to use it for a fake Items controller class Items < V1::Controllers::BaseController

include Praxis::Controller
include Praxis::Extensions::Rendering
implements V1::Endpoints::Items

include Praxis::Extensions::Pagination

def index(filters: nil, pagination: nil, order: nil,  **_args)
  items = current_user.items.all
  domain_model = self.media_type.domain_model
  items = domain_model.craft_pagination_query( query: items, pagination: _pagination)

  display(items)
end

end

This code will properly add the right clauses to the final query based on the pagination strategy and ordering and it will also generate the Link header with the appropriate relationships depending on the paging strategy. When total_count is requested in the pagination a header with TotalCount will also be included.

Public Instance Methods

_pagination() click to toggle source

Will set the typed paginator and order object into a controller ivar This is lazily evaluated and memoized, so there’s no need to only calculate things for actions that paginate/sort

# File lib/praxis/extensions/pagination.rb, line 61
def _pagination
  return @_pagination if @_pagination

  pagination = {}
  attrs = request.action&.params&.type&.attributes
  pagination[:paginator] = request.params.pagination if attrs&.key? :pagination
  pagination[:order] = request.params.order if attrs&.key? :order

  @_pagination = PaginationStruct.new(pagination[:paginator], pagination[:order])
end
build_pagination_headers(pagination:, current_url:, current_query_params:) click to toggle source
# File lib/praxis/extensions/pagination.rb, line 72
def build_pagination_headers(pagination:, current_url:, current_query_params:)
  links = if pagination.paginator.by
            # We're assuming that the last element has a "symbol/string" field with the same name of the "by" pagination.
            last_element = response.body.last
            last_value = last_element[pagination.paginator.by.to_sym] || last_element[pagination.paginator.by] if last_element
            HeaderGenerator.build_cursor_headers(
              paginator: pagination.paginator,
              last_value: last_value,
              total_count: pagination.total_count
            )
          else
            HeaderGenerator.build_paging_headers(
              paginator: pagination.paginator,
              total_count: pagination.total_count
            )
          end

  HeaderGenerator.generate_headers(
    links: links,
    current_url: current_url,
    current_query_params: current_query_params,
    total_count: pagination.total_count
  )
end