api-pagination 4.4.0 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/lib/api-pagination/configuration.rb +26 -7
- data/lib/api-pagination/hooks.rb +29 -16
- data/lib/api-pagination/railtie.rb +19 -0
- data/lib/api-pagination/version.rb +2 -2
- data/lib/api-pagination.rb +70 -15
- data/lib/grape/pagination.rb +12 -7
- data/lib/rails/pagination.rb +19 -8
- data/spec/active_record_spec.rb +50 -0
- data/spec/api-pagination_spec.rb +66 -20
- data/spec/grape_spec.rb +31 -2
- data/spec/rails_spec.rb +85 -65
- data/spec/sequel_spec.rb +1 -2
- data/spec/spec_helper.rb +9 -3
- data/spec/support/active_record/foo.rb +3 -0
- data/spec/support/active_record/schema.rb +5 -0
- data/spec/support/numbers_api.rb +19 -1
- data/spec/support/numbers_controller.rb +5 -2
- data/spec/support/shared_examples/first_page.rb +2 -2
- data/spec/support/shared_examples/last_page.rb +2 -2
- metadata +109 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 0aeee41828ccf353b3be509b5ddc10f180cb238d9b12bb8c357dc3ddfd35f07e
|
4
|
+
data.tar.gz: d2e33f4bf383e78f99d9e0d5ee6878e6fa54c8f9ad7412de18d23cadf45ec650
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c45ef1013c9a791da01d230be2f1a719af87a658b7ba7ab5a2643959eebe9bed8c7935f591f3077a8ed9db5822d561299a9fad87b8347faa3d45b7e6bab70cfc
|
7
|
+
data.tar.gz: 81e9f814f3ba16bcf86f1a07a26d7ac951e1dbc8a13221e9ef6db207861389ee301b6cb2c1923ff3deffc5718bc203070c0f4b77fca64535abe26f62590fdd6f
|
@@ -8,6 +8,10 @@ module ApiPagination
|
|
8
8
|
|
9
9
|
attr_accessor :include_total
|
10
10
|
|
11
|
+
attr_accessor :base_url
|
12
|
+
|
13
|
+
attr_accessor :response_formats
|
14
|
+
|
11
15
|
def configure(&block)
|
12
16
|
yield self
|
13
17
|
end
|
@@ -17,6 +21,8 @@ module ApiPagination
|
|
17
21
|
@per_page_header = 'Per-Page'
|
18
22
|
@page_header = nil
|
19
23
|
@include_total = true
|
24
|
+
@base_url = nil
|
25
|
+
@response_formats = [:json, :xml]
|
20
26
|
end
|
21
27
|
|
22
28
|
['page', 'per_page'].each do |param_name|
|
@@ -47,11 +53,17 @@ module ApiPagination
|
|
47
53
|
end
|
48
54
|
|
49
55
|
def paginator
|
50
|
-
|
56
|
+
if instance_variable_defined? :@paginator
|
57
|
+
@paginator
|
58
|
+
else
|
59
|
+
set_paginator
|
60
|
+
end
|
51
61
|
end
|
52
62
|
|
53
63
|
def paginator=(paginator)
|
54
64
|
case paginator.to_sym
|
65
|
+
when :pagy
|
66
|
+
use_pagy
|
55
67
|
when :kaminari
|
56
68
|
use_kaminari
|
57
69
|
when :will_paginate
|
@@ -64,11 +76,12 @@ module ApiPagination
|
|
64
76
|
private
|
65
77
|
|
66
78
|
def set_paginator
|
67
|
-
|
79
|
+
conditions = [defined?(Pagy), defined?(Kaminari), defined?(WillPaginate::CollectionMethods)]
|
80
|
+
if conditions.compact.size > 1
|
68
81
|
Kernel.warn <<-WARNING
|
69
|
-
Warning: api-pagination relies on
|
70
|
-
currently active. If possible, you should remove one or the other. If
|
71
|
-
you _must_ configure api-pagination on your own. For example:
|
82
|
+
Warning: api-pagination relies on Pagy, Kaminari, or WillPaginate, but more than
|
83
|
+
one are currently active. If possible, you should remove one or the other. If
|
84
|
+
you can't, you _must_ configure api-pagination on your own. For example:
|
72
85
|
|
73
86
|
ApiPagination.configure do |config|
|
74
87
|
config.paginator = :kaminari
|
@@ -83,13 +96,19 @@ Kaminari.configure do |config|
|
|
83
96
|
end
|
84
97
|
|
85
98
|
WARNING
|
99
|
+
elsif defined?(Pagy)
|
100
|
+
use_pagy
|
86
101
|
elsif defined?(Kaminari)
|
87
|
-
|
102
|
+
use_kaminari
|
88
103
|
elsif defined?(WillPaginate::CollectionMethods)
|
89
|
-
|
104
|
+
use_will_paginate
|
90
105
|
end
|
91
106
|
end
|
92
107
|
|
108
|
+
def use_pagy
|
109
|
+
@paginator = :pagy
|
110
|
+
end
|
111
|
+
|
93
112
|
def use_kaminari
|
94
113
|
require 'kaminari/models/array_extension'
|
95
114
|
@paginator = :kaminari
|
data/lib/api-pagination/hooks.rb
CHANGED
@@ -1,30 +1,43 @@
|
|
1
|
-
begin; require 'rails'; rescue LoadError; end
|
2
|
-
if defined?(ActionController::Base)
|
3
|
-
require 'rails/pagination'
|
4
|
-
ActionController::Base.send(:include, Rails::Pagination)
|
5
|
-
end
|
6
|
-
|
7
|
-
begin; require 'rails-api'; rescue LoadError; end
|
8
|
-
if defined?(ActionController::API)
|
9
|
-
require 'rails/pagination'
|
10
|
-
ActionController::API.send(:include, Rails::Pagination)
|
11
|
-
end
|
12
|
-
|
13
1
|
begin; require 'grape'; rescue LoadError; end
|
14
2
|
if defined?(Grape::API)
|
15
3
|
require 'grape/pagination'
|
16
|
-
|
4
|
+
|
5
|
+
klass = if Grape::VERSION >= '1.2.0' || defined?(Grape::API::Instance)
|
6
|
+
Grape::API::Instance
|
7
|
+
else
|
8
|
+
Grape::API
|
9
|
+
end
|
10
|
+
|
11
|
+
klass.send(:include, Grape::Pagination)
|
17
12
|
end
|
18
13
|
|
14
|
+
begin; require 'pagy'; rescue LoadError; end
|
19
15
|
begin; require 'kaminari'; rescue LoadError; end
|
20
16
|
begin; require 'will_paginate'; rescue LoadError; end
|
21
17
|
|
22
|
-
unless defined?(Kaminari) || defined?(WillPaginate::CollectionMethods)
|
18
|
+
unless defined?(Pagy) || defined?(Kaminari) || defined?(WillPaginate::CollectionMethods)
|
23
19
|
Kernel.warn <<-WARNING.gsub(/^\s{4}/, '')
|
24
|
-
Warning: api-pagination relies on either Kaminari or WillPaginate.
|
25
|
-
install
|
20
|
+
Warning: api-pagination relies on either Pagy, Kaminari, or WillPaginate.
|
21
|
+
Please install a paginator by adding one of the following to your Gemfile:
|
26
22
|
|
23
|
+
gem 'pagy'
|
27
24
|
gem 'kaminari'
|
28
25
|
gem 'will_paginate'
|
29
26
|
WARNING
|
30
27
|
end
|
28
|
+
|
29
|
+
if defined?(Rails)
|
30
|
+
module ApiPagination
|
31
|
+
module Hooks
|
32
|
+
def self.rails_parent_controller
|
33
|
+
if Rails::VERSION::MAJOR >= 5 || defined?(ActionController::API)
|
34
|
+
ActionController::API
|
35
|
+
else
|
36
|
+
ActionController::Base
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
require 'api-pagination/railtie'
|
43
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rails/railtie'
|
2
|
+
|
3
|
+
module ApiPagination
|
4
|
+
class Railtie < ::Rails::Railtie
|
5
|
+
initializer :api_pagination do
|
6
|
+
ActiveSupport.on_load(:action_controller) do
|
7
|
+
require 'rails/pagination'
|
8
|
+
|
9
|
+
klass = if Rails::VERSION::MAJOR >= 5 || defined?(ActionController::API)
|
10
|
+
ActionController::API
|
11
|
+
else
|
12
|
+
ActionController::Base
|
13
|
+
end
|
14
|
+
|
15
|
+
klass.send(:include, Rails::Pagination)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/api-pagination.rb
CHANGED
@@ -9,6 +9,8 @@ module ApiPagination
|
|
9
9
|
options[:per_page] = options[:per_page].to_i
|
10
10
|
|
11
11
|
case ApiPagination.config.paginator
|
12
|
+
when :pagy
|
13
|
+
paginate_with_pagy(collection, options)
|
12
14
|
when :kaminari
|
13
15
|
paginate_with_kaminari(collection, options, options[:paginate_array_options] || {})
|
14
16
|
when :will_paginate
|
@@ -18,15 +20,17 @@ module ApiPagination
|
|
18
20
|
end
|
19
21
|
end
|
20
22
|
|
21
|
-
def pages_from(collection)
|
23
|
+
def pages_from(collection, options = {})
|
24
|
+
return pagy_pages_from(collection) if ApiPagination.config.paginator == :pagy && collection.is_a?(Pagy)
|
25
|
+
|
22
26
|
{}.tap do |pages|
|
23
27
|
unless collection.first_page?
|
24
28
|
pages[:first] = 1
|
25
29
|
pages[:prev] = collection.current_page - 1
|
26
30
|
end
|
27
31
|
|
28
|
-
unless collection.last_page?
|
29
|
-
pages[:last] = collection.total_pages
|
32
|
+
unless collection.last_page? || (ApiPagination.config.paginator == :kaminari && collection.out_of_range?)
|
33
|
+
pages[:last] = collection.total_pages if ApiPagination.config.include_total
|
30
34
|
pages[:next] = collection.current_page + 1
|
31
35
|
end
|
32
36
|
end
|
@@ -34,6 +38,7 @@ module ApiPagination
|
|
34
38
|
|
35
39
|
def total_from(collection)
|
36
40
|
case ApiPagination.config.paginator
|
41
|
+
when :pagy then collection.count.to_s
|
37
42
|
when :kaminari then collection.total_count.to_s
|
38
43
|
when :will_paginate then collection.total_entries.to_s
|
39
44
|
end
|
@@ -41,6 +46,47 @@ module ApiPagination
|
|
41
46
|
|
42
47
|
private
|
43
48
|
|
49
|
+
def paginate_with_pagy(collection, options)
|
50
|
+
if Pagy::DEFAULT[:max_per_page] && options[:per_page] > Pagy::DEFAULT[:max_per_page]
|
51
|
+
options[:per_page] = Pagy::DEFAULT[:max_per_page]
|
52
|
+
elsif options[:per_page] <= 0
|
53
|
+
options[:per_page] = Pagy::DEFAULT[:limit]
|
54
|
+
end
|
55
|
+
|
56
|
+
pagy = pagy_from(collection, options)
|
57
|
+
collection = if collection.respond_to?(:offset) && collection.respond_to?(:limit)
|
58
|
+
collection.offset(pagy.offset).limit(pagy.limit)
|
59
|
+
else
|
60
|
+
collection[pagy.offset, pagy.limit]
|
61
|
+
end
|
62
|
+
|
63
|
+
return [collection, pagy]
|
64
|
+
end
|
65
|
+
|
66
|
+
def pagy_from(collection, options)
|
67
|
+
if options[:count]
|
68
|
+
count = options[:count]
|
69
|
+
else
|
70
|
+
count = collection.is_a?(Array) ? collection.count : collection.count(:all)
|
71
|
+
end
|
72
|
+
|
73
|
+
Pagy.new(count: count, limit: options[:per_page], page: options[:page])
|
74
|
+
end
|
75
|
+
|
76
|
+
def pagy_pages_from(pagy)
|
77
|
+
{}.tap do |pages|
|
78
|
+
unless pagy.page == 1
|
79
|
+
pages[:first] = 1
|
80
|
+
pages[:prev] = pagy.prev
|
81
|
+
end
|
82
|
+
|
83
|
+
unless pagy.page == pagy.pages
|
84
|
+
pages[:last] = pagy.pages if ApiPagination.config.include_total
|
85
|
+
pages[:next] = pagy.next
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
44
90
|
def paginate_with_kaminari(collection, options, paginate_array_options = {})
|
45
91
|
if Kaminari.config.max_per_page && options[:per_page] > Kaminari.config.max_per_page
|
46
92
|
options[:per_page] = Kaminari.config.max_per_page
|
@@ -48,8 +94,10 @@ module ApiPagination
|
|
48
94
|
options[:per_page] = get_default_per_page_for_kaminari(collection)
|
49
95
|
end
|
50
96
|
|
51
|
-
collection = Kaminari.paginate_array(collection, paginate_array_options) if collection.is_a?(Array)
|
52
|
-
collection.page(options[:page]).per(options[:per_page])
|
97
|
+
collection = Kaminari.paginate_array(collection, **paginate_array_options) if collection.is_a?(Array)
|
98
|
+
collection = collection.page(options[:page]).per(options[:per_page])
|
99
|
+
collection.without_count if !collection.is_a?(Array) && !ApiPagination.config.include_total
|
100
|
+
[collection, nil]
|
53
101
|
end
|
54
102
|
|
55
103
|
def paginate_with_will_paginate(collection, options)
|
@@ -57,29 +105,36 @@ module ApiPagination
|
|
57
105
|
options[:per_page] = default_per_page_for_will_paginate(collection)
|
58
106
|
end
|
59
107
|
|
60
|
-
if defined?(Sequel::Dataset) && collection.kind_of?(Sequel::Dataset)
|
108
|
+
collection = if defined?(Sequel::Dataset) && collection.kind_of?(Sequel::Dataset)
|
61
109
|
collection.paginate(options[:page], options[:per_page])
|
62
110
|
else
|
63
|
-
|
111
|
+
supported_options = [:page, :per_page, :total_entries]
|
112
|
+
options = options.dup.keep_if { |k,v| supported_options.include?(k.to_sym) }
|
113
|
+
collection.paginate(options)
|
64
114
|
end
|
115
|
+
|
116
|
+
[collection, nil]
|
65
117
|
end
|
66
118
|
|
67
119
|
def get_default_per_page_for_kaminari(collection)
|
68
120
|
default = Kaminari.config.default_per_page
|
69
|
-
|
70
|
-
rescue
|
71
|
-
default
|
121
|
+
extract_per_page_from_model(collection, :default_per_page) || default
|
72
122
|
end
|
73
123
|
|
74
124
|
def default_per_page_for_will_paginate(collection)
|
75
125
|
default = WillPaginate.per_page
|
76
|
-
|
77
|
-
rescue
|
78
|
-
default
|
126
|
+
extract_per_page_from_model(collection, :per_page) || default
|
79
127
|
end
|
80
128
|
|
81
|
-
def
|
82
|
-
collection.
|
129
|
+
def extract_per_page_from_model(collection, accessor)
|
130
|
+
klass = if collection.respond_to?(:klass)
|
131
|
+
collection.klass
|
132
|
+
else
|
133
|
+
collection.first.class
|
134
|
+
end
|
135
|
+
|
136
|
+
return unless klass.respond_to?(accessor)
|
137
|
+
klass.send(accessor)
|
83
138
|
end
|
84
139
|
end
|
85
140
|
end
|
data/lib/grape/pagination.rb
CHANGED
@@ -9,11 +9,11 @@ module Grape
|
|
9
9
|
:page => ApiPagination.config.page_param(params),
|
10
10
|
:per_page => [per_page, route_setting(:max_per_page)].compact.min
|
11
11
|
}
|
12
|
-
collection = ApiPagination.paginate(collection, options)
|
12
|
+
collection, pagy = ApiPagination.paginate(collection, options)
|
13
13
|
|
14
14
|
links = (header['Link'] || "").split(',').map(&:strip)
|
15
15
|
url = request.url.sub(/\?.*$/, '')
|
16
|
-
pages = ApiPagination.pages_from(collection)
|
16
|
+
pages = ApiPagination.pages_from(pagy || collection, options)
|
17
17
|
|
18
18
|
pages.each do |k, v|
|
19
19
|
old_params = Rack::Utils.parse_nested_query(request.query_string)
|
@@ -27,7 +27,7 @@ module Grape
|
|
27
27
|
include_total = ApiPagination.config.include_total
|
28
28
|
|
29
29
|
header 'Link', links.join(', ') unless links.empty?
|
30
|
-
header total_header, ApiPagination.total_from(collection) if include_total
|
30
|
+
header total_header, ApiPagination.total_from(pagy || collection).to_s if include_total
|
31
31
|
header per_page_header, options[:per_page].to_s
|
32
32
|
header page_header, options[:page].to_s unless page_header.nil?
|
33
33
|
|
@@ -39,11 +39,16 @@ module Grape
|
|
39
39
|
def self.paginate(options = {})
|
40
40
|
route_setting :per_page, options[:per_page]
|
41
41
|
route_setting :max_per_page, options[:max_per_page]
|
42
|
+
|
43
|
+
enforce_max_per_page = options[:max_per_page] && options[:enforce_max_per_page]
|
44
|
+
per_page_values = enforce_max_per_page ? 0..options[:max_per_page] : nil
|
45
|
+
|
42
46
|
params do
|
43
|
-
optional :page, :type
|
44
|
-
:desc
|
45
|
-
optional :per_page, :type
|
46
|
-
:desc
|
47
|
+
optional :page, :type => Integer, :default => 1,
|
48
|
+
:desc => 'Page of results to fetch.'
|
49
|
+
optional :per_page, :type => Integer, :default => options[:per_page],
|
50
|
+
:desc => 'Number of results to return per page.',
|
51
|
+
:values => per_page_values
|
47
52
|
end
|
48
53
|
end
|
49
54
|
end
|
data/lib/rails/pagination.rb
CHANGED
@@ -8,11 +8,12 @@ module Rails
|
|
8
8
|
|
9
9
|
return _paginate_collection(collection, options) if collection
|
10
10
|
|
11
|
-
|
11
|
+
response_format = _discover_format(options)
|
12
|
+
|
13
|
+
collection = options[response_format]
|
12
14
|
collection = _paginate_collection(collection, options)
|
13
15
|
|
14
|
-
options[
|
15
|
-
options[:xml] = collection if options[:xml]
|
16
|
+
options[response_format] = collection if options[response_format]
|
16
17
|
|
17
18
|
render options
|
18
19
|
end
|
@@ -23,15 +24,21 @@ module Rails
|
|
23
24
|
|
24
25
|
private
|
25
26
|
|
27
|
+
def _discover_format(options)
|
28
|
+
for response_format in ApiPagination.config.response_formats
|
29
|
+
return response_format if options.key?(response_format)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
26
33
|
def _paginate_collection(collection, options={})
|
27
34
|
options[:page] = ApiPagination.config.page_param(params)
|
28
35
|
options[:per_page] ||= ApiPagination.config.per_page_param(params)
|
29
36
|
|
30
|
-
collection = ApiPagination.paginate(collection, options)
|
37
|
+
collection, pagy = ApiPagination.paginate(collection, options)
|
31
38
|
|
32
|
-
links = (headers['Link'] ||
|
33
|
-
url = request.
|
34
|
-
pages = ApiPagination.pages_from(collection)
|
39
|
+
links = (headers['Link'] || '').split(',').map(&:strip)
|
40
|
+
url = base_url + request.path_info
|
41
|
+
pages = ApiPagination.pages_from(pagy || collection, options)
|
35
42
|
|
36
43
|
pages.each do |k, v|
|
37
44
|
new_params = request.query_parameters.merge(:page => v)
|
@@ -46,7 +53,7 @@ module Rails
|
|
46
53
|
headers['Link'] = links.join(', ') unless links.empty?
|
47
54
|
headers[per_page_header] = options[:per_page].to_s
|
48
55
|
headers[page_header] = options[:page].to_s unless page_header.nil?
|
49
|
-
headers[total_header] = total_count(collection, options) if include_total
|
56
|
+
headers[total_header] = total_count(pagy || collection, options).to_s if include_total
|
50
57
|
|
51
58
|
return collection
|
52
59
|
end
|
@@ -58,5 +65,9 @@ module Rails
|
|
58
65
|
end
|
59
66
|
total_count || ApiPagination.total_from(collection)
|
60
67
|
end
|
68
|
+
|
69
|
+
def base_url
|
70
|
+
ApiPagination.config.base_url || request.base_url
|
71
|
+
end
|
61
72
|
end
|
62
73
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'support/active_record/foo'
|
3
|
+
require 'nulldb_rspec'
|
4
|
+
|
5
|
+
ActiveRecord::Base.establish_connection(
|
6
|
+
adapter: :nulldb,
|
7
|
+
schema: 'spec/support/active_record/schema.rb'
|
8
|
+
)
|
9
|
+
|
10
|
+
NullDB.configure { |ndb| def ndb.project_root; Dir.pwd; end; }
|
11
|
+
|
12
|
+
shared_examples 'produces_correct_sql' do
|
13
|
+
it 'produces correct sql for first page' do
|
14
|
+
allow(collection).to receive(:count).and_return(collection_size)
|
15
|
+
paginated_sql, _ = ApiPagination.paginate(collection, per_page: per_page)
|
16
|
+
expect(paginated_sql.to_sql).to eql(Foo.limit(per_page).offset(0).to_sql)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe 'ActiveRecord Support' do
|
21
|
+
let(:collection) { Foo.all }
|
22
|
+
let(:collection_size) { 50 }
|
23
|
+
let(:per_page) { 5 }
|
24
|
+
|
25
|
+
if ApiPagination.config.paginator == :will_paginate
|
26
|
+
require 'will_paginate/active_record'
|
27
|
+
end
|
28
|
+
|
29
|
+
context "pagination with #{ApiPagination.config.paginator}" do
|
30
|
+
include_examples 'produces_correct_sql'
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
if ApiPagination.config.paginator != :pagy
|
35
|
+
context 'reflections' do
|
36
|
+
it 'invokes the correct methods to determine type' do
|
37
|
+
expect(collection).to receive(:klass).at_least(:once)
|
38
|
+
.and_call_original
|
39
|
+
ApiPagination.paginate(collection)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'does not fail if table name is not snake cased class name' do
|
43
|
+
allow(collection).to receive(:table_name).and_return(SecureRandom.uuid)
|
44
|
+
expect { ApiPagination.paginate(collection) }.to_not raise_error
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
data/spec/api-pagination_spec.rb
CHANGED
@@ -1,30 +1,76 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe ApiPagination do
|
4
|
-
let(:collection) {
|
5
|
-
let(:
|
4
|
+
let(:collection) {(1..100).to_a}
|
5
|
+
let(:active_record_relation) {double("ActiveRecord_Relation").as_null_object}
|
6
|
+
let(:paginate_array_options) {{ total_count: 1000 }}
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
describe "#paginate" do
|
9
|
+
if ENV['PAGINATOR'].to_sym == :kaminari
|
10
|
+
context 'Using kaminari' do
|
11
|
+
describe '.paginate' do
|
12
|
+
it 'should accept paginate_array_options option' do
|
13
|
+
expect(Kaminari).to receive(:paginate_array)
|
14
|
+
.with(collection, **paginate_array_options)
|
15
|
+
.and_call_original
|
16
|
+
|
17
|
+
ApiPagination.paginate(
|
18
|
+
collection,
|
19
|
+
{
|
20
|
+
per_page: 30,
|
21
|
+
paginate_array_options: paginate_array_options
|
22
|
+
}
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'configured not to include the total' do
|
27
|
+
before { ApiPagination.config.include_total = false }
|
28
|
+
|
29
|
+
context 'and paginating an array' do
|
30
|
+
it 'should not call without_count on the collection' do
|
31
|
+
expect(collection).to_not receive :without_count
|
32
|
+
ApiPagination.paginate(collection)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
context 'and paginating an active record relation' do
|
36
|
+
it 'should call without_count on the relation' do
|
37
|
+
expect(active_record_relation).to receive :without_count
|
38
|
+
ApiPagination.paginate(active_record_relation)
|
39
|
+
end
|
40
|
+
end
|
11
41
|
|
12
|
-
|
13
|
-
|
42
|
+
after { ApiPagination.config.include_total = true }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '.pages_from' do
|
47
|
+
subject { described_class.pages_from(collection) }
|
48
|
+
|
49
|
+
context 'on empty collection' do
|
50
|
+
let(:collection) { ApiPagination.paginate([], page: 1).first }
|
51
|
+
|
52
|
+
it { is_expected.to be_empty }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
14
56
|
end
|
15
57
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
58
|
+
if ENV['PAGINATOR'].to_sym == :will_paginate
|
59
|
+
context 'Using will_paginate' do
|
60
|
+
context 'passing in total_entries in options' do
|
61
|
+
it 'should set total_entries using the passed in value' do
|
62
|
+
paginated_collection = ApiPagination.paginate(collection, total_entries: 3000).first
|
63
|
+
expect(paginated_collection.total_entries).to eq(3000)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'passing in collection only' do
|
68
|
+
it 'should set total_entries using the size of the collection ' do
|
69
|
+
paginated_collection = ApiPagination.paginate(collection).first
|
70
|
+
expect(paginated_collection.total_entries).to eq(100)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
28
74
|
end
|
29
75
|
end
|
30
76
|
end
|
data/spec/grape_spec.rb
CHANGED
@@ -5,8 +5,11 @@ require 'support/shared_examples/middle_page'
|
|
5
5
|
require 'support/shared_examples/last_page'
|
6
6
|
|
7
7
|
describe NumbersAPI do
|
8
|
+
it { is_expected.to be_kind_of(Grape::Pagination) }
|
9
|
+
|
8
10
|
describe 'GET #index' do
|
9
|
-
let(:
|
11
|
+
let(:link) { last_response.headers['Link'] }
|
12
|
+
let(:links) { link.split(', ') }
|
10
13
|
let(:total) { last_response.headers['Total'].to_i }
|
11
14
|
let(:per_page) { last_response.headers['Per-Page'].to_i }
|
12
15
|
|
@@ -56,15 +59,35 @@ describe NumbersAPI do
|
|
56
59
|
it_behaves_like 'an endpoint with a middle page'
|
57
60
|
end
|
58
61
|
|
59
|
-
context '
|
62
|
+
context 'without a max_per_page setting' do
|
60
63
|
before { get '/numbers', :count => 100, :per_page => 30 }
|
61
64
|
|
65
|
+
it 'should list all numbers within per page in the response body' do
|
66
|
+
body = '[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]'
|
67
|
+
|
68
|
+
expect(last_response.body).to eq(body)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'with a max_per_page setting not enforced' do
|
73
|
+
before { get '/numbers_with_max_per_page', :count => 100, :per_page => 30 }
|
74
|
+
|
62
75
|
it 'should not go above the max_per_page_limit' do
|
63
76
|
body = '[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]'
|
64
77
|
|
65
78
|
expect(last_response.body).to eq(body)
|
66
79
|
end
|
67
80
|
end
|
81
|
+
|
82
|
+
context 'with a max_per_page setting enforced' do
|
83
|
+
before { get '/numbers_with_enforced_max_per_page', :count => 100, :per_page => 30 }
|
84
|
+
|
85
|
+
it 'should not allow value above the max_per_page_limit' do
|
86
|
+
body = '{"error":"per_page does not have a valid value"}'
|
87
|
+
|
88
|
+
expect(last_response.body).to eq(body)
|
89
|
+
end
|
90
|
+
end
|
68
91
|
end
|
69
92
|
|
70
93
|
context 'with custom response headers' do
|
@@ -119,6 +142,12 @@ describe NumbersAPI do
|
|
119
142
|
expect(last_response.header['Total']).to be_nil
|
120
143
|
end
|
121
144
|
|
145
|
+
it 'should not include a link with rel "last"' do
|
146
|
+
get '/numbers', count: 100
|
147
|
+
|
148
|
+
expect(link).to_not include('rel="last"')
|
149
|
+
end
|
150
|
+
|
122
151
|
after { ApiPagination.config.include_total = true }
|
123
152
|
end
|
124
153
|
|
data/spec/rails_spec.rb
CHANGED
@@ -8,12 +8,13 @@ describe NumbersController, :type => :controller do
|
|
8
8
|
before { request.host = 'example.org' }
|
9
9
|
|
10
10
|
describe 'GET #index' do
|
11
|
-
let(:
|
11
|
+
let(:link) { response.headers['Link'] }
|
12
|
+
let(:links) { link.split(', ') }
|
12
13
|
let(:total) { response.headers['Total'].to_i }
|
13
14
|
let(:per_page) { response.headers['Per-Page'].to_i }
|
14
15
|
|
15
16
|
context 'without enough items to give more than one page' do
|
16
|
-
before { get :index, :count
|
17
|
+
before { get :index, params: {count: 10} }
|
17
18
|
|
18
19
|
it 'should not paginate' do
|
19
20
|
expect(response.headers.keys).not_to include('Link')
|
@@ -34,26 +35,26 @@ describe NumbersController, :type => :controller do
|
|
34
35
|
end
|
35
36
|
|
36
37
|
context 'with existing Link headers' do
|
37
|
-
before { get :index, :count
|
38
|
+
before { get :index, params: {count: 30, with_headers: true} }
|
38
39
|
|
39
40
|
it_behaves_like 'an endpoint with existing Link headers'
|
40
41
|
end
|
41
42
|
|
42
43
|
context 'with enough items to paginate' do
|
43
44
|
context 'when on the first page' do
|
44
|
-
before { get :index, :count
|
45
|
+
before { get :index, params: {count: 100} }
|
45
46
|
|
46
47
|
it_behaves_like 'an endpoint with a first page'
|
47
48
|
end
|
48
49
|
|
49
50
|
context 'when on the last page' do
|
50
|
-
before { get :index, :count
|
51
|
+
before { get :index, params: {count: 100, page: 10} }
|
51
52
|
|
52
53
|
it_behaves_like 'an endpoint with a last page'
|
53
54
|
end
|
54
55
|
|
55
56
|
context 'when somewhere comfortably in the middle' do
|
56
|
-
before { get :index, :count
|
57
|
+
before { get :index, params: {count: 100, page: 2} }
|
57
58
|
|
58
59
|
it_behaves_like 'an endpoint with a middle page'
|
59
60
|
end
|
@@ -61,7 +62,7 @@ describe NumbersController, :type => :controller do
|
|
61
62
|
|
62
63
|
context 'providing a block' do
|
63
64
|
it 'yields to the block instead of implicitly rendering' do
|
64
|
-
get :index_with_custom_render, :count
|
65
|
+
get :index_with_custom_render, params: {count: 100}
|
65
66
|
|
66
67
|
json = { numbers: (1..10).map { |n| { number: n } } }.to_json
|
67
68
|
|
@@ -74,19 +75,23 @@ describe NumbersController, :type => :controller do
|
|
74
75
|
ApiPagination.config.total_header = 'X-Total-Count'
|
75
76
|
ApiPagination.config.per_page_header = 'X-Per-Page'
|
76
77
|
ApiPagination.config.page_header = 'X-Page'
|
78
|
+
ApiPagination.config.base_url = 'http://guybrush:3000'
|
77
79
|
|
78
|
-
get :index,
|
80
|
+
get :index, params: params
|
79
81
|
end
|
80
82
|
|
81
83
|
after do
|
82
84
|
ApiPagination.config.total_header = 'Total'
|
83
85
|
ApiPagination.config.per_page_header = 'Per-Page'
|
84
86
|
ApiPagination.config.page_header = nil
|
87
|
+
ApiPagination.config.base_url = nil
|
85
88
|
end
|
86
89
|
|
90
|
+
let(:params) { { count: 10 } }
|
87
91
|
let(:total) { response.header['X-Total-Count'].to_i }
|
88
92
|
let(:per_page) { response.header['X-Per-Page'].to_i }
|
89
93
|
let(:page) { response.header['X-Page'].to_i }
|
94
|
+
let(:link) { response.header['Link'] }
|
90
95
|
|
91
96
|
it 'should give a X-Total-Count header' do
|
92
97
|
headers_keys = response.headers.keys
|
@@ -110,17 +115,32 @@ describe NumbersController, :type => :controller do
|
|
110
115
|
expect(headers_keys).to include('X-Page')
|
111
116
|
expect(page).to eq(1)
|
112
117
|
end
|
118
|
+
|
119
|
+
context 'with paginated result' do
|
120
|
+
let(:params) { { count: 20 } }
|
121
|
+
it 'should use custom base_url in the Link header' do
|
122
|
+
|
123
|
+
expect(response.headers['Link']).to eq(
|
124
|
+
'<http://guybrush:3000/numbers?count=20&page=2>; rel="last", <http://guybrush:3000/numbers?count=20&page=2>; rel="next"')
|
125
|
+
end
|
126
|
+
end
|
113
127
|
end
|
114
128
|
|
115
129
|
context 'configured not to include the total' do
|
116
130
|
before { ApiPagination.config.include_total = false }
|
117
131
|
|
118
132
|
it 'should not include a Total header' do
|
119
|
-
get :index, count: 10
|
133
|
+
get :index, params: {count: 10}
|
120
134
|
|
121
135
|
expect(response.header['Total']).to be_nil
|
122
136
|
end
|
123
137
|
|
138
|
+
it 'should not include a link with rel "last"' do
|
139
|
+
get :index, params: { count: 100 }
|
140
|
+
|
141
|
+
expect(link).to_not include('rel="last"')
|
142
|
+
end
|
143
|
+
|
124
144
|
after { ApiPagination.config.include_total = true }
|
125
145
|
end
|
126
146
|
|
@@ -137,7 +157,7 @@ describe NumbersController, :type => :controller do
|
|
137
157
|
end
|
138
158
|
|
139
159
|
it 'should work' do
|
140
|
-
get :index, :foo
|
160
|
+
get :index, params: {foo: 2, count: 100}
|
141
161
|
|
142
162
|
expect(response.header['Page']).to eq('2')
|
143
163
|
end
|
@@ -158,7 +178,7 @@ describe NumbersController, :type => :controller do
|
|
158
178
|
end
|
159
179
|
|
160
180
|
it 'should work' do
|
161
|
-
get :index, :foo
|
181
|
+
get :index, params: {foo: {bar: 2}, count: 100}
|
162
182
|
|
163
183
|
expect(response.header['Page']).to eq('2')
|
164
184
|
end
|
@@ -176,7 +196,7 @@ describe NumbersController, :type => :controller do
|
|
176
196
|
end
|
177
197
|
|
178
198
|
it 'should work' do
|
179
|
-
get :index_with_no_per_page, :foo
|
199
|
+
get :index_with_no_per_page, params: {foo: 2, count: 100}
|
180
200
|
|
181
201
|
expect(response.header['Per-Page']).to eq('2')
|
182
202
|
end
|
@@ -194,15 +214,18 @@ describe NumbersController, :type => :controller do
|
|
194
214
|
end
|
195
215
|
|
196
216
|
it 'should work' do
|
197
|
-
get :index_with_no_per_page, :foo
|
217
|
+
get :index_with_no_per_page, params: {foo: {bar: 2}, count: 100}
|
198
218
|
|
199
219
|
expect(response.header['Per-Page']).to eq('2')
|
200
220
|
end
|
201
221
|
end
|
202
222
|
end
|
203
223
|
|
204
|
-
|
205
|
-
|
224
|
+
if ApiPagination.config.paginator.to_sym == :kaminari
|
225
|
+
context 'paginate array options' do
|
226
|
+
let(:paginate_array_total_count) { 300 }
|
227
|
+
let(:total_header) { 300 }
|
228
|
+
let(:count) { 50 }
|
206
229
|
let(:params) do
|
207
230
|
{
|
208
231
|
paginate_array_total_count: paginate_array_total_count,
|
@@ -210,78 +233,75 @@ describe NumbersController, :type => :controller do
|
|
210
233
|
}
|
211
234
|
end
|
212
235
|
|
213
|
-
|
214
|
-
get :index_with_paginate_array_options, params
|
236
|
+
it 'has a properly set Total header' do
|
237
|
+
get :index_with_paginate_array_options, params: params
|
238
|
+
|
239
|
+
expect(response.header['Total']).to be_kind_of(String)
|
215
240
|
expect(response.header['Total'].to_i).to eq total_header
|
216
241
|
end
|
217
242
|
end
|
243
|
+
end
|
218
244
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
end
|
245
|
+
if [:will_paginate, :kaminari].include?(ApiPagination.config.paginator.to_sym)
|
246
|
+
context 'default per page in model' do
|
247
|
+
before do
|
248
|
+
class Fixnum
|
249
|
+
@default_per_page = 6
|
250
|
+
@per_page = 6
|
226
251
|
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
252
|
+
class << self
|
253
|
+
attr_accessor :default_per_page, :per_page
|
254
|
+
end
|
255
|
+
end
|
231
256
|
end
|
232
|
-
end
|
233
257
|
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
ApiPagination.config.paginator = paginator
|
258
|
+
after do
|
259
|
+
class Fixnum
|
260
|
+
@default_per_page = 25
|
261
|
+
@per_page = 25
|
262
|
+
end
|
240
263
|
end
|
241
264
|
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
265
|
+
after :all do
|
266
|
+
class Fixnum
|
267
|
+
class << self
|
268
|
+
undef_method :default_per_page, :per_page
|
269
|
+
end
|
270
|
+
end
|
246
271
|
end
|
247
|
-
end
|
248
|
-
end
|
249
272
|
|
250
|
-
|
251
|
-
|
252
|
-
class Fixnum
|
253
|
-
@default_per_page = 6
|
254
|
-
@per_page = 6
|
273
|
+
it 'should use default per page from model' do
|
274
|
+
get :index_with_no_per_page, params: {count: 100}
|
255
275
|
|
256
|
-
|
257
|
-
attr_accessor :default_per_page, :per_page
|
258
|
-
end
|
276
|
+
expect(response.header['Per-Page']).to eq('6')
|
259
277
|
end
|
260
|
-
end
|
261
278
|
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
end
|
279
|
+
it 'should not fail if the model yields nil for per page' do
|
280
|
+
class Fixnum
|
281
|
+
@default_per_page = nil
|
282
|
+
@per_page = nil
|
283
|
+
end
|
268
284
|
|
269
|
-
|
270
|
-
get :index_with_no_per_page, count: 100
|
285
|
+
get :index_with_no_per_page, params: {count: 100}
|
271
286
|
|
272
|
-
|
287
|
+
expect(response.header['Per-Page']).to eq(
|
288
|
+
case ApiPagination.config.paginator
|
289
|
+
when :pagy then Pagy::DEFAULT[:limit].to_s
|
290
|
+
when :kaminari then Kaminari.config.default_per_page.to_s
|
291
|
+
when :will_paginate then WillPaginate.per_page.to_s
|
292
|
+
end
|
293
|
+
)
|
294
|
+
end
|
273
295
|
end
|
296
|
+
end
|
274
297
|
|
298
|
+
context 'default per page in objects without paginator defaults' do
|
275
299
|
it 'should not fail if model does not respond to per page' do
|
276
|
-
|
277
|
-
@default_per_page = nil
|
278
|
-
@per_page = nil
|
279
|
-
end
|
280
|
-
|
281
|
-
get :index_with_no_per_page, count: 100
|
300
|
+
get :index_with_no_per_page, params: {count: 100}
|
282
301
|
|
283
302
|
expect(response.header['Per-Page']).to eq(
|
284
303
|
case ApiPagination.config.paginator
|
304
|
+
when :pagy then Pagy::DEFAULT[:limit].to_s
|
285
305
|
when :kaminari then Kaminari.config.default_per_page.to_s
|
286
306
|
when :will_paginate then WillPaginate.per_page.to_s
|
287
307
|
end
|
data/spec/sequel_spec.rb
CHANGED
@@ -23,9 +23,8 @@ if ApiPagination.config.paginator == :will_paginate
|
|
23
23
|
end
|
24
24
|
|
25
25
|
it 'returns a Sequel::Dataset' do
|
26
|
-
collection = ApiPagination.paginate(people)
|
26
|
+
collection = ApiPagination.paginate(people).first
|
27
27
|
expect(collection.kind_of?(Sequel::Dataset)).to be_truthy
|
28
28
|
end
|
29
29
|
end
|
30
30
|
end
|
31
|
-
|
data/spec/spec_helper.rb
CHANGED
@@ -3,14 +3,20 @@ require 'support/numbers_api'
|
|
3
3
|
require 'api-pagination'
|
4
4
|
|
5
5
|
if ENV['PAGINATOR'].nil?
|
6
|
-
warn
|
7
|
-
|
6
|
+
warn <<-WARNING
|
7
|
+
No PAGINATOR set. Defaulting to pagy.
|
8
|
+
|
9
|
+
To test against kaminari, run `PAGINATOR=kaminari bundle exec rspec`
|
10
|
+
To test against will_paginate, run `PAGINATOR=will_paginate bundle exec rspec`
|
11
|
+
WARNING
|
12
|
+
|
13
|
+
ENV['PAGINATOR'] = 'pagy'
|
8
14
|
end
|
9
15
|
|
10
16
|
require ENV['PAGINATOR']
|
11
17
|
ApiPagination.config.paginator = ENV['PAGINATOR'].to_sym
|
12
18
|
|
13
|
-
require 'will_paginate/array'
|
19
|
+
require 'will_paginate/array' if ENV['PAGINATOR'].to_sym == :will_paginate
|
14
20
|
|
15
21
|
RSpec.configure do |config|
|
16
22
|
config.include Rack::Test::Methods
|
data/spec/support/numbers_api.rb
CHANGED
@@ -5,7 +5,7 @@ class NumbersAPI < Grape::API
|
|
5
5
|
format :json
|
6
6
|
|
7
7
|
desc 'Return some paginated set of numbers'
|
8
|
-
paginate :per_page => 10
|
8
|
+
paginate :per_page => 10
|
9
9
|
params do
|
10
10
|
requires :count, :type => Integer
|
11
11
|
optional :with_headers, :default => false, :type => Boolean
|
@@ -20,4 +20,22 @@ class NumbersAPI < Grape::API
|
|
20
20
|
|
21
21
|
paginate (1..params[:count]).to_a
|
22
22
|
end
|
23
|
+
|
24
|
+
desc 'Return some paginated set of numbers with max_per_page'
|
25
|
+
paginate :per_page => 10, :max_per_page => 25
|
26
|
+
params do
|
27
|
+
requires :count, :type => Integer
|
28
|
+
end
|
29
|
+
get :numbers_with_max_per_page do
|
30
|
+
paginate (1..params[:count]).to_a
|
31
|
+
end
|
32
|
+
|
33
|
+
desc 'Return some paginated set of numbers with max_per_page enforced'
|
34
|
+
paginate :per_page => 10, :max_per_page => 25, :enforce_max_per_page => true
|
35
|
+
params do
|
36
|
+
requires :count, :type => Integer
|
37
|
+
end
|
38
|
+
get :numbers_with_enforced_max_per_page do
|
39
|
+
paginate (1..params[:count]).to_a
|
40
|
+
end
|
23
41
|
end
|
@@ -1,4 +1,5 @@
|
|
1
|
-
require 'action_controller'
|
1
|
+
require 'action_controller/railtie'
|
2
|
+
require 'api-pagination/hooks'
|
2
3
|
require 'ostruct'
|
3
4
|
|
4
5
|
module Rails
|
@@ -58,7 +59,7 @@ class NumbersSerializer
|
|
58
59
|
end
|
59
60
|
end
|
60
61
|
|
61
|
-
class NumbersController < ActionController::
|
62
|
+
class NumbersController < ActionController::API
|
62
63
|
include Rails.application.routes.url_helpers
|
63
64
|
|
64
65
|
def index
|
@@ -98,3 +99,5 @@ class NumbersController < ActionController::Base
|
|
98
99
|
render json: NumbersSerializer.new(numbers)
|
99
100
|
end
|
100
101
|
end
|
102
|
+
|
103
|
+
ApiPagination::Railtie.initializers.each(&:run)
|
@@ -1,10 +1,10 @@
|
|
1
1
|
shared_examples 'an endpoint with a first page' do
|
2
2
|
it 'should not give a link with rel "first"' do
|
3
|
-
expect(
|
3
|
+
expect(link).not_to include('rel="first"')
|
4
4
|
end
|
5
5
|
|
6
6
|
it 'should not give a link with rel "prev"' do
|
7
|
-
expect(
|
7
|
+
expect(link).not_to include('rel="prev"')
|
8
8
|
end
|
9
9
|
|
10
10
|
it 'should give a link with rel "last"' do
|
@@ -1,10 +1,10 @@
|
|
1
1
|
shared_examples 'an endpoint with a last page' do
|
2
2
|
it 'should not give a link with rel "last"' do
|
3
|
-
expect(
|
3
|
+
expect(link).not_to include('rel="last"')
|
4
4
|
end
|
5
5
|
|
6
6
|
it 'should not give a link with rel "next"' do
|
7
|
-
expect(
|
7
|
+
expect(link).not_to include('rel="next"')
|
8
8
|
end
|
9
9
|
|
10
10
|
it 'should give a link with rel "first"' do
|
metadata
CHANGED
@@ -1,85 +1,165 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: api-pagination
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 6.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Celis
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-07-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: kaminari
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '1.2'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.2.1
|
20
23
|
type: :development
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
24
27
|
- - "~>"
|
25
28
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
29
|
+
version: '1.2'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.2.1
|
27
33
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
34
|
+
name: pagy
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '9.0'
|
40
|
+
type: :development
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '9.0'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: will_paginate
|
29
49
|
requirement: !ruby/object:Gem::Requirement
|
30
50
|
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '3.3'
|
31
54
|
- - ">="
|
32
55
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
56
|
+
version: 3.3.1
|
34
57
|
type: :development
|
35
58
|
prerelease: false
|
36
59
|
version_requirements: !ruby/object:Gem::Requirement
|
37
60
|
requirements:
|
61
|
+
- - "~>"
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '3.3'
|
38
64
|
- - ">="
|
39
65
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
66
|
+
version: 3.3.1
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: rspec
|
69
|
+
requirement: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - "~>"
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '3.10'
|
74
|
+
type: :development
|
75
|
+
prerelease: false
|
76
|
+
version_requirements: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - "~>"
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '3.10'
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: grape
|
83
|
+
requirement: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - "~>"
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '1.6'
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - "~>"
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '1.6'
|
41
95
|
- !ruby/object:Gem::Dependency
|
42
96
|
name: railties
|
43
97
|
requirement: !ruby/object:Gem::Requirement
|
44
98
|
requirements:
|
99
|
+
- - "~>"
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '6.1'
|
45
102
|
- - ">="
|
46
103
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
104
|
+
version: 6.1.4.1
|
48
105
|
type: :development
|
49
106
|
prerelease: false
|
50
107
|
version_requirements: !ruby/object:Gem::Requirement
|
51
108
|
requirements:
|
109
|
+
- - "~>"
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '6.1'
|
52
112
|
- - ">="
|
53
113
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
114
|
+
version: 6.1.4.1
|
55
115
|
- !ruby/object:Gem::Dependency
|
56
116
|
name: actionpack
|
57
117
|
requirement: !ruby/object:Gem::Requirement
|
58
118
|
requirements:
|
119
|
+
- - "~>"
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '6.1'
|
59
122
|
- - ">="
|
60
123
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
124
|
+
version: 6.1.4.1
|
62
125
|
type: :development
|
63
126
|
prerelease: false
|
64
127
|
version_requirements: !ruby/object:Gem::Requirement
|
65
128
|
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '6.1'
|
66
132
|
- - ">="
|
67
133
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
134
|
+
version: 6.1.4.1
|
69
135
|
- !ruby/object:Gem::Dependency
|
70
136
|
name: sequel
|
71
137
|
requirement: !ruby/object:Gem::Requirement
|
72
138
|
requirements:
|
73
|
-
- - "
|
139
|
+
- - "~>"
|
74
140
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
141
|
+
version: '5.49'
|
76
142
|
type: :development
|
77
143
|
prerelease: false
|
78
144
|
version_requirements: !ruby/object:Gem::Requirement
|
79
145
|
requirements:
|
80
|
-
- - "
|
146
|
+
- - "~>"
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: '5.49'
|
149
|
+
- !ruby/object:Gem::Dependency
|
150
|
+
name: activerecord-nulldb-adapter
|
151
|
+
requirement: !ruby/object:Gem::Requirement
|
152
|
+
requirements:
|
153
|
+
- - "~>"
|
81
154
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
155
|
+
version: 0.7.0
|
156
|
+
type: :development
|
157
|
+
prerelease: false
|
158
|
+
version_requirements: !ruby/object:Gem::Requirement
|
159
|
+
requirements:
|
160
|
+
- - "~>"
|
161
|
+
- !ruby/object:Gem::Version
|
162
|
+
version: 0.7.0
|
83
163
|
description: Link header pagination for Rails and Grape APIs
|
84
164
|
email:
|
85
165
|
- me@davidcel.is
|
@@ -90,14 +170,18 @@ files:
|
|
90
170
|
- lib/api-pagination.rb
|
91
171
|
- lib/api-pagination/configuration.rb
|
92
172
|
- lib/api-pagination/hooks.rb
|
173
|
+
- lib/api-pagination/railtie.rb
|
93
174
|
- lib/api-pagination/version.rb
|
94
175
|
- lib/grape/pagination.rb
|
95
176
|
- lib/rails/pagination.rb
|
177
|
+
- spec/active_record_spec.rb
|
96
178
|
- spec/api-pagination_spec.rb
|
97
179
|
- spec/grape_spec.rb
|
98
180
|
- spec/rails_spec.rb
|
99
181
|
- spec/sequel_spec.rb
|
100
182
|
- spec/spec_helper.rb
|
183
|
+
- spec/support/active_record/foo.rb
|
184
|
+
- spec/support/active_record/schema.rb
|
101
185
|
- spec/support/numbers_api.rb
|
102
186
|
- spec/support/numbers_controller.rb
|
103
187
|
- spec/support/shared_examples/existing_headers.rb
|
@@ -108,32 +192,34 @@ homepage: https://github.com/davidcelis/api-pagination
|
|
108
192
|
licenses:
|
109
193
|
- MIT
|
110
194
|
metadata: {}
|
111
|
-
post_install_message:
|
195
|
+
post_install_message:
|
112
196
|
rdoc_options: []
|
113
197
|
require_paths:
|
114
198
|
- lib
|
115
199
|
required_ruby_version: !ruby/object:Gem::Requirement
|
116
200
|
requirements:
|
117
|
-
- - "
|
201
|
+
- - ">"
|
118
202
|
- !ruby/object:Gem::Version
|
119
|
-
version: '
|
203
|
+
version: '2.7'
|
120
204
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
121
205
|
requirements:
|
122
206
|
- - ">="
|
123
207
|
- !ruby/object:Gem::Version
|
124
208
|
version: '0'
|
125
209
|
requirements: []
|
126
|
-
|
127
|
-
|
128
|
-
signing_key:
|
210
|
+
rubygems_version: 3.5.16
|
211
|
+
signing_key:
|
129
212
|
specification_version: 4
|
130
213
|
summary: Link header pagination for Rails and Grape APIs. Don't use the request body.
|
131
214
|
test_files:
|
215
|
+
- spec/active_record_spec.rb
|
132
216
|
- spec/api-pagination_spec.rb
|
133
217
|
- spec/grape_spec.rb
|
134
218
|
- spec/rails_spec.rb
|
135
219
|
- spec/sequel_spec.rb
|
136
220
|
- spec/spec_helper.rb
|
221
|
+
- spec/support/active_record/foo.rb
|
222
|
+
- spec/support/active_record/schema.rb
|
137
223
|
- spec/support/numbers_api.rb
|
138
224
|
- spec/support/numbers_controller.rb
|
139
225
|
- spec/support/shared_examples/existing_headers.rb
|