api-pagination 4.8.1 → 4.8.2
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 +4 -4
- data/lib/api-pagination.rb +19 -13
- data/lib/api-pagination/configuration.rb +8 -1
- data/lib/api-pagination/hooks.rb +8 -1
- data/lib/api-pagination/version.rb +1 -1
- data/lib/grape/pagination.rb +1 -1
- data/lib/rails/pagination.rb +10 -3
- data/spec/active_record_spec.rb +50 -0
- data/spec/api-pagination_spec.rb +34 -12
- data/spec/grape_spec.rb +10 -1
- data/spec/rails_spec.rb +32 -3
- data/spec/support/active_record/foo.rb +3 -0
- data/spec/support/active_record/schema.rb +5 -0
- data/spec/support/shared_examples/first_page.rb +2 -2
- data/spec/support/shared_examples/last_page.rb +2 -2
- metadata +22 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e0006fcbe882c8a54820796eaf3d573d04b3dd2057cb9d6130b56389dff36790
|
4
|
+
data.tar.gz: b585330048fb81eb9b83c377af32ea85d3fd80afcc864b70a01426e0d51c1bf4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e79b9e403a5a30834d9bd94e11687a79e08ac049463fe749b025dc98cd476ed11b98e0667b6e01f13315c9bf374d19fb500af6e0a98a1cecb1bf2753101be9ef
|
7
|
+
data.tar.gz: '0398d5cab6c18f426823f8d99ef02a3796380047f87c99864600cfd0ff52bb86246f4d3091f8b3d95decd1f34827323792eebe2d77502abe05bcc235a7993382'
|
data/lib/api-pagination.rb
CHANGED
@@ -30,7 +30,7 @@ module ApiPagination
|
|
30
30
|
end
|
31
31
|
|
32
32
|
unless collection.last_page? || (ApiPagination.config.paginator == :kaminari && collection.out_of_range?)
|
33
|
-
pages[:last] = collection.total_pages
|
33
|
+
pages[:last] = collection.total_pages if ApiPagination.config.include_total
|
34
34
|
pages[:next] = collection.current_page + 1
|
35
35
|
end
|
36
36
|
end
|
@@ -64,7 +64,12 @@ module ApiPagination
|
|
64
64
|
end
|
65
65
|
|
66
66
|
def pagy_from(collection, options)
|
67
|
-
|
67
|
+
if options[:count]
|
68
|
+
count = options[:count]
|
69
|
+
else
|
70
|
+
count = collection.is_a?(Array) ? collection.count : collection.count(:all)
|
71
|
+
end
|
72
|
+
|
68
73
|
Pagy.new(count: count, items: options[:per_page], page: options[:page])
|
69
74
|
end
|
70
75
|
|
@@ -76,7 +81,7 @@ module ApiPagination
|
|
76
81
|
end
|
77
82
|
|
78
83
|
unless pagy.page == pagy.pages
|
79
|
-
pages[:last] = pagy.pages
|
84
|
+
pages[:last] = pagy.pages if ApiPagination.config.include_total
|
80
85
|
pages[:next] = pagy.next
|
81
86
|
end
|
82
87
|
end
|
@@ -90,7 +95,9 @@ module ApiPagination
|
|
90
95
|
end
|
91
96
|
|
92
97
|
collection = Kaminari.paginate_array(collection, paginate_array_options) if collection.is_a?(Array)
|
93
|
-
|
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]
|
94
101
|
end
|
95
102
|
|
96
103
|
def paginate_with_will_paginate(collection, options)
|
@@ -111,24 +118,23 @@ module ApiPagination
|
|
111
118
|
|
112
119
|
def get_default_per_page_for_kaminari(collection)
|
113
120
|
default = Kaminari.config.default_per_page
|
114
|
-
|
115
|
-
rescue
|
116
|
-
default
|
121
|
+
extract_per_page_from_model(collection, :default_per_page) || default
|
117
122
|
end
|
118
123
|
|
119
124
|
def default_per_page_for_will_paginate(collection)
|
120
125
|
default = WillPaginate.per_page
|
121
|
-
|
122
|
-
rescue
|
123
|
-
default
|
126
|
+
extract_per_page_from_model(collection, :per_page) || default
|
124
127
|
end
|
125
128
|
|
126
|
-
def
|
127
|
-
if collection.respond_to?(:
|
128
|
-
collection.
|
129
|
+
def extract_per_page_from_model(collection, accessor)
|
130
|
+
klass = if collection.respond_to?(:klass)
|
131
|
+
collection.klass
|
129
132
|
else
|
130
133
|
collection.first.class
|
131
134
|
end
|
135
|
+
|
136
|
+
return unless klass.respond_to?(accessor)
|
137
|
+
klass.send(accessor)
|
132
138
|
end
|
133
139
|
end
|
134
140
|
end
|
@@ -10,6 +10,8 @@ module ApiPagination
|
|
10
10
|
|
11
11
|
attr_accessor :base_url
|
12
12
|
|
13
|
+
attr_accessor :response_formats
|
14
|
+
|
13
15
|
def configure(&block)
|
14
16
|
yield self
|
15
17
|
end
|
@@ -20,6 +22,7 @@ module ApiPagination
|
|
20
22
|
@page_header = nil
|
21
23
|
@include_total = true
|
22
24
|
@base_url = nil
|
25
|
+
@response_formats = [:json, :xml]
|
23
26
|
end
|
24
27
|
|
25
28
|
['page', 'per_page'].each do |param_name|
|
@@ -50,7 +53,11 @@ module ApiPagination
|
|
50
53
|
end
|
51
54
|
|
52
55
|
def paginator
|
53
|
-
|
56
|
+
if instance_variable_defined? :@paginator
|
57
|
+
@paginator
|
58
|
+
else
|
59
|
+
set_paginator
|
60
|
+
end
|
54
61
|
end
|
55
62
|
|
56
63
|
def paginator=(paginator)
|
data/lib/api-pagination/hooks.rb
CHANGED
@@ -1,7 +1,14 @@
|
|
1
1
|
begin; require 'grape'; rescue LoadError; end
|
2
2
|
if defined?(Grape::API)
|
3
3
|
require 'grape/pagination'
|
4
|
-
|
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)
|
5
12
|
end
|
6
13
|
|
7
14
|
begin; require 'pagy'; rescue LoadError; end
|
data/lib/grape/pagination.rb
CHANGED
@@ -46,7 +46,7 @@ module Grape
|
|
46
46
|
params do
|
47
47
|
optional :page, :type => Integer, :default => 1,
|
48
48
|
:desc => 'Page of results to fetch.'
|
49
|
-
optional :per_page, :type => Integer,
|
49
|
+
optional :per_page, :type => Integer, :default => options[:per_page],
|
50
50
|
:desc => 'Number of results to return per page.',
|
51
51
|
:values => per_page_values
|
52
52
|
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,6 +24,12 @@ 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)
|
@@ -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
@@ -2,23 +2,45 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe ApiPagination do
|
4
4
|
let(:collection) {(1..100).to_a}
|
5
|
+
let(:active_record_relation) {double("ActiveRecord_Relation").as_null_object}
|
5
6
|
let(:paginate_array_options) {{ total_count: 1000 }}
|
6
7
|
|
7
8
|
describe "#paginate" do
|
8
9
|
if ENV['PAGINATOR'].to_sym == :kaminari
|
9
10
|
context 'Using kaminari' do
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
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
|
41
|
+
|
42
|
+
after { ApiPagination.config.include_total = true }
|
43
|
+
end
|
22
44
|
end
|
23
45
|
|
24
46
|
describe '.pages_from' do
|
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
|
|
@@ -139,6 +142,12 @@ describe NumbersAPI do
|
|
139
142
|
expect(last_response.header['Total']).to be_nil
|
140
143
|
end
|
141
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
|
+
|
142
151
|
after { ApiPagination.config.include_total = true }
|
143
152
|
end
|
144
153
|
|
data/spec/rails_spec.rb
CHANGED
@@ -8,7 +8,8 @@ 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
|
|
@@ -134,6 +135,12 @@ describe NumbersController, :type => :controller do
|
|
134
135
|
expect(response.header['Total']).to be_nil
|
135
136
|
end
|
136
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
|
+
|
137
144
|
after { ApiPagination.config.include_total = true }
|
138
145
|
end
|
139
146
|
|
@@ -255,13 +262,21 @@ describe NumbersController, :type => :controller do
|
|
255
262
|
end
|
256
263
|
end
|
257
264
|
|
265
|
+
after :all do
|
266
|
+
class Fixnum
|
267
|
+
class << self
|
268
|
+
undef_method :default_per_page, :per_page
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
258
273
|
it 'should use default per page from model' do
|
259
274
|
get :index_with_no_per_page, params: {count: 100}
|
260
275
|
|
261
276
|
expect(response.header['Per-Page']).to eq('6')
|
262
277
|
end
|
263
278
|
|
264
|
-
it 'should not fail if model
|
279
|
+
it 'should not fail if the model yields nil for per page' do
|
265
280
|
class Fixnum
|
266
281
|
@default_per_page = nil
|
267
282
|
@per_page = nil
|
@@ -279,5 +294,19 @@ describe NumbersController, :type => :controller do
|
|
279
294
|
end
|
280
295
|
end
|
281
296
|
end
|
297
|
+
|
298
|
+
context 'default per page in objects without paginator defaults' do
|
299
|
+
it 'should not fail if model does not respond to per page' do
|
300
|
+
get :index_with_no_per_page, params: {count: 100}
|
301
|
+
|
302
|
+
expect(response.header['Per-Page']).to eq(
|
303
|
+
case ApiPagination.config.paginator
|
304
|
+
when :pagy then Pagy::VARS[:items].to_s
|
305
|
+
when :kaminari then Kaminari.config.default_per_page.to_s
|
306
|
+
when :will_paginate then WillPaginate.per_page.to_s
|
307
|
+
end
|
308
|
+
)
|
309
|
+
end
|
310
|
+
end
|
282
311
|
end
|
283
|
-
end
|
312
|
+
end
|
@@ -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,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: api-pagination
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.8.
|
4
|
+
version: 4.8.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Celis
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-12-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: 4.9.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: activerecord-nulldb-adapter
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.3.9
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.3.9
|
83
97
|
description: Link header pagination for Rails and Grape APIs
|
84
98
|
email:
|
85
99
|
- me@davidcel.is
|
@@ -94,11 +108,14 @@ files:
|
|
94
108
|
- lib/api-pagination/version.rb
|
95
109
|
- lib/grape/pagination.rb
|
96
110
|
- lib/rails/pagination.rb
|
111
|
+
- spec/active_record_spec.rb
|
97
112
|
- spec/api-pagination_spec.rb
|
98
113
|
- spec/grape_spec.rb
|
99
114
|
- spec/rails_spec.rb
|
100
115
|
- spec/sequel_spec.rb
|
101
116
|
- spec/spec_helper.rb
|
117
|
+
- spec/support/active_record/foo.rb
|
118
|
+
- spec/support/active_record/schema.rb
|
102
119
|
- spec/support/numbers_api.rb
|
103
120
|
- spec/support/numbers_controller.rb
|
104
121
|
- spec/support/shared_examples/existing_headers.rb
|
@@ -132,9 +149,12 @@ summary: Link header pagination for Rails and Grape APIs. Don't use the request
|
|
132
149
|
test_files:
|
133
150
|
- spec/spec_helper.rb
|
134
151
|
- spec/api-pagination_spec.rb
|
152
|
+
- spec/active_record_spec.rb
|
135
153
|
- spec/sequel_spec.rb
|
136
154
|
- spec/support/numbers_api.rb
|
137
155
|
- spec/support/numbers_controller.rb
|
156
|
+
- spec/support/active_record/foo.rb
|
157
|
+
- spec/support/active_record/schema.rb
|
138
158
|
- spec/support/shared_examples/first_page.rb
|
139
159
|
- spec/support/shared_examples/middle_page.rb
|
140
160
|
- spec/support/shared_examples/last_page.rb
|