-
Notifications
You must be signed in to change notification settings - Fork 137
/
Copy pathapi-pagination.rb
145 lines (120 loc) · 4.68 KB
/
api-pagination.rb
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
143
144
145
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::VARS[:max_per_page] && options[:per_page] > Pagy::VARS[:max_per_page]
options[:per_page] = Pagy::VARS[:max_per_page]
elsif options[:per_page] <= 0
options[:per_page] = Pagy::VARS[: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
if collection.is_a?(Array) || (options.key?(:paginate_array) && !!options[:paginate_array])
collection = Kaminari.paginate_array(collection, paginate_array_options)
end
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'