lib/jsonapi/paginator.rb
# frozen_string_literal: true
module JSONAPI
class Paginator
def initialize(_params)
end
def apply(_relation, _order_options)
# relation
end
def links_page_params(_options = {})
# :nocov:
{}
# :nocov:
end
class << self
def requires_record_count
# :nocov:
false
# :nocov:
end
def paginator_for(paginator)
paginator_class_name = "#{paginator.to_s.camelize}Paginator"
paginator_class_name.safe_constantize if paginator_class_name
end
end
end
end
class OffsetPaginator < JSONAPI::Paginator
attr_reader :limit, :offset
def initialize(params)
parse_pagination_params(params)
verify_pagination_params
end
def self.requires_record_count
true
end
def apply(relation, _order_options)
relation.offset(@offset).limit(@limit)
end
def links_page_params(options = {})
record_count = options[:record_count]
links_page_params = {}
links_page_params['first'] = {
'offset' => 0,
'limit' => @limit
}
if @offset > 0
previous_offset = @offset - @limit
previous_offset = 0 if previous_offset < 0
links_page_params['prev'] = {
'offset' => previous_offset,
'limit' => @limit
}
end
next_offset = @offset + @limit
unless next_offset >= record_count
links_page_params['next'] = {
'offset' => next_offset,
'limit' => @limit
}
end
if record_count
last_offset = record_count - @limit
last_offset = 0 if last_offset < 0
links_page_params['last'] = {
'offset' => last_offset,
'limit' => @limit
}
end
links_page_params
end
private
def parse_pagination_params(params)
if params.nil?
@offset = 0
@limit = JSONAPI.configuration.default_page_size
elsif params.is_a?(ActionController::Parameters)
validparams = params.permit(:offset, :limit)
@offset = validparams[:offset] ? validparams[:offset].to_i : 0
@limit = validparams[:limit] ? validparams[:limit].to_i : JSONAPI.configuration.default_page_size
else
fail JSONAPI::Exceptions::InvalidPageObject.new
end
rescue ActionController::UnpermittedParameters => e
raise JSONAPI::Exceptions::PageParametersNotAllowed.new(e.params)
end
def verify_pagination_params
if @limit < 1
fail JSONAPI::Exceptions::InvalidPageValue.new(:limit, @limit)
elsif @limit > JSONAPI.configuration.maximum_page_size
fail JSONAPI::Exceptions::InvalidPageValue.new(:limit, @limit,
detail: "Limit exceeds maximum page size of #{JSONAPI.configuration.maximum_page_size}.")
end
if @offset < 0
fail JSONAPI::Exceptions::InvalidPageValue.new(:offset, @offset)
end
end
end
class PagedPaginator < JSONAPI::Paginator
attr_reader :size, :number
def initialize(params)
parse_pagination_params(params)
verify_pagination_params
end
def self.requires_record_count
true
end
def calculate_page_count(record_count)
(record_count / @size.to_f).ceil
end
def apply(relation, _order_options)
offset = (@number - 1) * @size
relation.offset(offset).limit(@size)
end
def links_page_params(options = {})
record_count = options[:record_count]
page_count = calculate_page_count(record_count)
links_page_params = {}
links_page_params['first'] = {
'number' => 1,
'size' => @size
}
if @number > 1
links_page_params['prev'] = {
'number' => @number - 1,
'size' => @size
}
end
unless @number >= page_count
links_page_params['next'] = {
'number' => @number + 1,
'size' => @size
}
end
if record_count
links_page_params['last'] = {
'number' => page_count == 0 ? 1 : page_count,
'size' => @size
}
end
links_page_params
end
private
def parse_pagination_params(params)
if params.nil?
@number = 1
@size = JSONAPI.configuration.default_page_size
elsif params.is_a?(ActionController::Parameters)
validparams = params.permit(:number, :size)
@size = validparams[:size] ? validparams[:size].to_i : JSONAPI.configuration.default_page_size
@number = validparams[:number] ? validparams[:number].to_i : 1
else
@size = JSONAPI.configuration.default_page_size
@number = params.to_i
end
rescue ActionController::UnpermittedParameters => e
raise JSONAPI::Exceptions::PageParametersNotAllowed.new(e.params)
end
def verify_pagination_params
if @size < 1
fail JSONAPI::Exceptions::InvalidPageValue.new(:size, @size)
elsif @size > JSONAPI.configuration.maximum_page_size
fail JSONAPI::Exceptions::InvalidPageValue.new(:size, @size,
detail: "size exceeds maximum page size of #{JSONAPI.configuration.maximum_page_size}.")
end
if @number < 1
fail JSONAPI::Exceptions::InvalidPageValue.new(:number, @number)
end
end
end