1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 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 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
require 'api-pagination/configuration'
require 'api-pagination/version'
module ApiPagination
class << self
def paginate(collection, options = {})
options[:page] = options[:page].to_i
options[:page] = 1 if options[:page] <= 0
options[:per_page] = options[:per_page].to_i
case ApiPagination.config.paginator
when :pagy
paginate_with_pagy(collection, options)
when :kaminari
paginate_with_kaminari(collection, options, options[:paginate_array_options] || {})
when :will_paginate
paginate_with_will_paginate(collection, options)
else
raise StandardError, "Unknown paginator: #{ApiPagination.config.paginator}"
end
end
def pages_from(collection, options = {})
return pagy_pages_from(collection) if ApiPagination.config.paginator == :pagy && collection.is_a?(Pagy)
{}.tap do |pages|
unless collection.first_page?
pages[:first] = 1
pages[:prev] = collection.current_page - 1
end
unless collection.last_page? || (ApiPagination.config.paginator == :kaminari && collection.out_of_range?)
pages[:last] = collection.total_pages if ApiPagination.config.include_total
pages[:next] = collection.current_page + 1
end
end
end
def total_from(collection)
case ApiPagination.config.paginator
when :pagy then collection.count.to_s
when :kaminari then collection.total_count.to_s
when :will_paginate then collection.total_entries.to_s
end
end
private
def paginate_with_pagy(collection, options)
if Pagy::DEFAULT[:max_per_page] && options[:per_page] > Pagy::DEFAULT[:max_per_page]
options[:per_page] = Pagy::DEFAULT[:max_per_page]
elsif options[:per_page] <= 0
options[:per_page] = Pagy::DEFAULT[:items]
end
pagy = pagy_from(collection, options)
collection = if collection.respond_to?(:offset) && collection.respond_to?(:limit)
collection.offset(pagy.offset).limit(pagy.items)
else
collection[pagy.offset, pagy.items]
end
return [collection, pagy]
end
def pagy_from(collection, options)
if options[:count]
count = options[:count]
else
count = collection.is_a?(Array) ? collection.count : collection.count(:all)
end
Pagy.new(count: count, items: options[:per_page], page: options[:page])
end
def pagy_pages_from(pagy)
{}.tap do |pages|
unless pagy.page == 1
pages[:first] = 1
pages[:prev] = pagy.prev
end
unless pagy.page == pagy.pages
pages[:last] = pagy.pages if ApiPagination.config.include_total
pages[:next] = pagy.next
end
end
end
def paginate_with_kaminari(collection, options, paginate_array_options = {})
if Kaminari.config.max_per_page && options[:per_page] > Kaminari.config.max_per_page
options[:per_page] = Kaminari.config.max_per_page
elsif options[:per_page] <= 0
options[:per_page] = get_default_per_page_for_kaminari(collection)
end
collection = Kaminari.paginate_array(collection, **paginate_array_options) if collection.is_a?(Array)
collection = collection.page(options[:page]).per(options[:per_page])
collection.without_count if !collection.is_a?(Array) && !ApiPagination.config.include_total
[collection, nil]
end
def paginate_with_will_paginate(collection, options)
if options[:per_page] <= 0
options[:per_page] = default_per_page_for_will_paginate(collection)
end
collection = if defined?(Sequel::Dataset) && collection.kind_of?(Sequel::Dataset)
collection.paginate(options[:page], options[:per_page])
else
supported_options = [:page, :per_page, :total_entries]
options = options.dup.keep_if { |k,v| supported_options.include?(k.to_sym) }
collection.paginate(options)
end
[collection, nil]
end
def get_default_per_page_for_kaminari(collection)
default = Kaminari.config.default_per_page
extract_per_page_from_model(collection, :default_per_page) || default
end
def default_per_page_for_will_paginate(collection)
default = WillPaginate.per_page
extract_per_page_from_model(collection, :per_page) || default
end
def extract_per_page_from_model(collection, accessor)
klass = if collection.respond_to?(:klass)
collection.klass
else
collection.first.class
end
return unless klass.respond_to?(accessor)
klass.send(accessor)
end
end
end
require 'api-pagination/hooks'
|