api-pagination 4.7.2 → 5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fcd1a8e55bce363ef14c8fca2ff4a06ea1cf325e61fe2eba564d6bcbcb0cbb43
4
- data.tar.gz: 66a8a77cc4e1fa163ce3e644c2828388778efaab24783967c2c9e7986a83ac30
3
+ metadata.gz: ba0df72041cd862671500fd9efe94c7fe8e35975877e0e9bbcd1c0b77860e4a4
4
+ data.tar.gz: debcf49e29dcda50d93cd31a2e9efec2332541dbe38f6bdaa488b450e5bb7d09
5
5
  SHA512:
6
- metadata.gz: 475209b5986a009d9bc52cded5269fec22998e6d94c419635772950ee17ea7a1b0a01818b6791f009fe9da545022522f2ba0303a5fae93d81a364f3bc740cb1e
7
- data.tar.gz: 355d8e7786bf49318941d48ea57ff6fd81fd6cf9b97d9e185fb1302eb20dc4144100f3fce675809d73bffc0341b0f100e37fb3f12a2e6c51ea9b98e4d9db5a03
6
+ metadata.gz: 4661d9bfa18456e1c6fcfb837ef4c3acbc9e35dd983299201340dc077056e3f5632c39a8f718b285d66b4e3985aec23da68a56c8c278f0fc850f27626352bb0b
7
+ data.tar.gz: 688fae38d680fb9f1b133a627172d687c7fa6f56186039a88a5bfe238e396c5310359266580644d7719b981d6f3589ac884f6b6d88688c497c8516cbffd122cd
@@ -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,11 +53,17 @@ module ApiPagination
50
53
  end
51
54
 
52
55
  def paginator
53
- @paginator || set_paginator
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)
57
64
  case paginator.to_sym
65
+ when :pagy
66
+ use_pagy
58
67
  when :kaminari
59
68
  use_kaminari
60
69
  when :will_paginate
@@ -67,11 +76,12 @@ module ApiPagination
67
76
  private
68
77
 
69
78
  def set_paginator
70
- if defined?(Kaminari) && defined?(WillPaginate::CollectionMethods)
79
+ conditions = [defined?(Pagy), defined?(Kaminari), defined?(WillPaginate::CollectionMethods)]
80
+ if conditions.compact.size > 1
71
81
  Kernel.warn <<-WARNING
72
- Warning: api-pagination relies on either Kaminari or WillPaginate, but both are
73
- currently active. If possible, you should remove one or the other. If you can't,
74
- 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:
75
85
 
76
86
  ApiPagination.configure do |config|
77
87
  config.paginator = :kaminari
@@ -86,13 +96,19 @@ Kaminari.configure do |config|
86
96
  end
87
97
 
88
98
  WARNING
99
+ elsif defined?(Pagy)
100
+ use_pagy
89
101
  elsif defined?(Kaminari)
90
- return use_kaminari
102
+ use_kaminari
91
103
  elsif defined?(WillPaginate::CollectionMethods)
92
- return use_will_paginate
104
+ use_will_paginate
93
105
  end
94
106
  end
95
107
 
108
+ def use_pagy
109
+ @paginator = :pagy
110
+ end
111
+
96
112
  def use_kaminari
97
113
  require 'kaminari/models/array_extension'
98
114
  @paginator = :kaminari
@@ -1,17 +1,26 @@
1
1
  begin; require 'grape'; rescue LoadError; end
2
2
  if defined?(Grape::API)
3
3
  require 'grape/pagination'
4
- Grape::API.send(:include, Grape::Pagination)
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
 
14
+ begin; require 'pagy'; rescue LoadError; end
7
15
  begin; require 'kaminari'; rescue LoadError; end
8
16
  begin; require 'will_paginate'; rescue LoadError; end
9
17
 
10
- unless defined?(Kaminari) || defined?(WillPaginate::CollectionMethods)
18
+ unless defined?(Pagy) || defined?(Kaminari) || defined?(WillPaginate::CollectionMethods)
11
19
  Kernel.warn <<-WARNING.gsub(/^\s{4}/, '')
12
- Warning: api-pagination relies on either Kaminari or WillPaginate. Please
13
- install either dependency by adding one of the following to your Gemfile:
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:
14
22
 
23
+ gem 'pagy'
15
24
  gem 'kaminari'
16
25
  gem 'will_paginate'
17
26
  WARNING
@@ -1,8 +1,8 @@
1
1
  module ApiPagination
2
2
  class Version
3
- MAJOR = 4
4
- MINOR = 7
5
- PATCH = 2
3
+ MAJOR = 5
4
+ MINOR = 0
5
+ PATCH = 0
6
6
 
7
7
  def self.to_s
8
8
  [MAJOR, MINOR, PATCH].join('.')
@@ -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,7 +20,9 @@ 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
@@ -26,7 +30,7 @@ module ApiPagination
26
30
  end
27
31
 
28
32
  unless collection.last_page? || (ApiPagination.config.paginator == :kaminari && collection.out_of_range?)
29
- pages[:last] = collection.total_pages
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[:items]
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.items)
59
+ else
60
+ collection[pagy.offset, pagy.items]
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, items: 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,35 +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]
64
112
  options = options.dup.keep_if { |k,v| supported_options.include?(k.to_sym) }
65
113
  collection.paginate(options)
66
114
  end
115
+
116
+ [collection, nil]
67
117
  end
68
118
 
69
119
  def get_default_per_page_for_kaminari(collection)
70
120
  default = Kaminari.config.default_per_page
71
- detect_model(collection).default_per_page || default
72
- rescue
73
- default
121
+ extract_per_page_from_model(collection, :default_per_page) || default
74
122
  end
75
123
 
76
124
  def default_per_page_for_will_paginate(collection)
77
125
  default = WillPaginate.per_page
78
- detect_model(collection).per_page || default
79
- rescue
80
- default
126
+ extract_per_page_from_model(collection, :per_page) || default
81
127
  end
82
128
 
83
- def detect_model(collection)
84
- if collection.respond_to?(:table_name)
85
- collection.table_name.classify.constantize
129
+ def extract_per_page_from_model(collection, accessor)
130
+ klass = if collection.respond_to?(:klass)
131
+ collection.klass
86
132
  else
87
133
  collection.first.class
88
134
  end
135
+
136
+ return unless klass.respond_to?(accessor)
137
+ klass.send(accessor)
89
138
  end
90
139
  end
91
140
  end
@@ -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).to_s 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
 
@@ -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
@@ -8,11 +8,12 @@ module Rails
8
8
 
9
9
  return _paginate_collection(collection, options) if collection
10
10
 
11
- collection = options[:json] || options[:xml]
11
+ response_format = _discover_format(options)
12
+
13
+ collection = options[response_format]
12
14
  collection = _paginate_collection(collection, options)
13
15
 
14
- options[:json] = collection if options[:json]
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
39
  links = (headers['Link'] || '').split(',').map(&:strip)
33
40
  url = base_url + request.path_info
34
- pages = ApiPagination.pages_from(collection)
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).to_s 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
@@ -62,6 +69,5 @@ module Rails
62
69
  def base_url
63
70
  ApiPagination.config.base_url || request.base_url
64
71
  end
65
-
66
72
  end
67
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
+
@@ -2,63 +2,73 @@ 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
- context 'Using kaminari' do
9
- before do
10
- ApiPagination.config.paginator = :kaminari
11
- end
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
12
16
 
13
- after do
14
- ApiPagination.config.paginator = ENV['PAGINATOR'].to_sym
15
- end
17
+ ApiPagination.paginate(
18
+ collection,
19
+ {
20
+ per_page: 30,
21
+ paginate_array_options: paginate_array_options
22
+ }
23
+ )
24
+ end
16
25
 
17
- it 'should accept paginate_array_options option' do
18
- expect(Kaminari).to receive(:paginate_array)
19
- .with(collection, paginate_array_options)
20
- .and_call_original
26
+ context 'configured not to include the total' do
27
+ before { ApiPagination.config.include_total = false }
21
28
 
22
- ApiPagination.paginate(
23
- collection,
24
- {
25
- per_page: 30,
26
- paginate_array_options: paginate_array_options
27
- }
28
- )
29
- end
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
44
+ end
30
45
 
31
- describe '.pages_from' do
32
- subject {described_class.pages_from collection}
46
+ describe '.pages_from' do
47
+ subject { described_class.pages_from(collection) }
33
48
 
34
- context 'on empty collection' do
35
- let(:collection) {ApiPagination.paginate [], page: 1}
49
+ context 'on empty collection' do
50
+ let(:collection) { ApiPagination.paginate([], page: 1).first }
36
51
 
37
- it {is_expected.to be_empty}
52
+ it { is_expected.to be_empty }
53
+ end
38
54
  end
39
55
  end
40
56
  end
41
57
 
42
- context 'Using will_paginate' do
43
- before do
44
- ApiPagination.config.paginator = :will_paginate
45
- end
46
-
47
- after do
48
- ApiPagination.config.paginator = ENV['PAGINATOR'].to_sym
49
- end
50
-
51
- context 'passing in total_entries in options' do
52
- it 'should set total_entries using the passed in value' do
53
- paginated_collection = ApiPagination.paginate(collection, total_entries: 3000)
54
- expect(paginated_collection.total_entries).to eq(3000)
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
55
65
  end
56
- end
57
66
 
58
- context 'passing in collection only' do
59
- it 'should set total_entries using the size of the collection ' do
60
- paginated_collection = ApiPagination.paginate(collection)
61
- expect(paginated_collection.total_entries).to eq(100)
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
62
72
  end
63
73
  end
64
74
  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(:links) { last_response.headers['Link'].split(', ') }
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(:links) { response.headers['Link'].split(', ') }
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
 
@@ -214,8 +221,11 @@ describe NumbersController, :type => :controller do
214
221
  end
215
222
  end
216
223
 
217
- context 'paginate array options' do
218
- shared_examples 'properly set Total header' do
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 }
219
229
  let(:params) do
220
230
  {
221
231
  paginate_array_total_count: paginate_array_total_count,
@@ -223,80 +233,75 @@ describe NumbersController, :type => :controller do
223
233
  }
224
234
  end
225
235
 
226
- specify do
236
+ it 'has a properly set Total header' do
227
237
  get :index_with_paginate_array_options, params: params
228
238
 
229
239
  expect(response.header['Total']).to be_kind_of(String)
230
240
  expect(response.header['Total'].to_i).to eq total_header
231
241
  end
232
242
  end
243
+ end
233
244
 
234
- context 'kaminari' do
235
- around do |example|
236
- paginator = ApiPagination.config.paginator
237
- ApiPagination.config.paginator = :kaminari
238
- example.run
239
- ApiPagination.config.paginator = paginator
240
- 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
241
251
 
242
- it_should_behave_like 'properly set Total header' do
243
- let(:paginate_array_total_count) { 300 }
244
- let(:total_header) { 300 }
245
- let(:count) { 50 }
252
+ class << self
253
+ attr_accessor :default_per_page, :per_page
254
+ end
255
+ end
246
256
  end
247
- end
248
257
 
249
- context 'will_paginate' do
250
- around do |example|
251
- paginator = ApiPagination.config.paginator
252
- ApiPagination.config.paginator = :will_paginate
253
- example.run
254
- ApiPagination.config.paginator = paginator
258
+ after do
259
+ class Fixnum
260
+ @default_per_page = 25
261
+ @per_page = 25
262
+ end
255
263
  end
256
264
 
257
- it_should_behave_like 'properly set Total header' do
258
- let(:paginate_array_total_count) { 300 }
259
- let(:total_header) { 50 }
260
- let(:count) { 50 }
265
+ after :all do
266
+ class Fixnum
267
+ class << self
268
+ undef_method :default_per_page, :per_page
269
+ end
270
+ end
261
271
  end
262
- end
263
- end
264
272
 
265
- context 'default per page in model' do
266
- before do
267
- class Fixnum
268
- @default_per_page = 6
269
- @per_page = 6
273
+ it 'should use default per page from model' do
274
+ get :index_with_no_per_page, params: {count: 100}
270
275
 
271
- class << self
272
- attr_accessor :default_per_page, :per_page
273
- end
276
+ expect(response.header['Per-Page']).to eq('6')
274
277
  end
275
- end
276
278
 
277
- after do
278
- class Fixnum
279
- @default_per_page = 25
280
- @per_page = 25
281
- end
282
- 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
283
284
 
284
- it 'should use default per page from model' do
285
- get :index_with_no_per_page, params: {count: 100}
285
+ get :index_with_no_per_page, params: {count: 100}
286
286
 
287
- expect(response.header['Per-Page']).to eq('6')
287
+ expect(response.header['Per-Page']).to eq(
288
+ case ApiPagination.config.paginator
289
+ when :pagy then Pagy::DEFAULT[:items].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
288
295
  end
296
+ end
289
297
 
298
+ context 'default per page in objects without paginator defaults' do
290
299
  it 'should not fail if model does not respond to per page' do
291
- class Fixnum
292
- @default_per_page = nil
293
- @per_page = nil
294
- end
295
-
296
300
  get :index_with_no_per_page, params: {count: 100}
297
301
 
298
302
  expect(response.header['Per-Page']).to eq(
299
303
  case ApiPagination.config.paginator
304
+ when :pagy then Pagy::DEFAULT[:items].to_s
300
305
  when :kaminari then Kaminari.config.default_per_page.to_s
301
306
  when :will_paginate then WillPaginate.per_page.to_s
302
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 'No PAGINATOR set. Defaulting to kaminari. To test against will_paginate, run `PAGINATOR=will_paginate bundle exec rspec`'
7
- ENV['PAGINATOR'] = 'kaminari'
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
@@ -0,0 +1,3 @@
1
+ require 'active_record'
2
+
3
+ class Foo < ActiveRecord::Base; end
@@ -0,0 +1,5 @@
1
+ ActiveRecord::Schema.define(version: 0) do
2
+ create_table "foos", :force => true do |t|
3
+ t.string "foo"
4
+ end
5
+ 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(links).not_to include('rel="first"')
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(links).not_to include('rel="prev"')
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(links).not_to include('rel="last"')
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(links).not_to include('rel="next"')
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,171 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: api-pagination
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.7.2
4
+ version: 5.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: 2018-06-08 00:00:00.000000000 Z
11
+ date: 2021-10-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rspec
14
+ name: kaminari
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '3.0'
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: '3.0'
29
+ version: '1.2'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 1.2.1
27
33
  - !ruby/object:Gem::Dependency
28
- name: grape
34
+ name: pagy
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '5.1'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 5.1.2
43
+ type: :development
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '5.1'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 5.1.2
53
+ - !ruby/object:Gem::Dependency
54
+ name: will_paginate
29
55
  requirement: !ruby/object:Gem::Requirement
30
56
  requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '3.3'
31
60
  - - ">="
32
61
  - !ruby/object:Gem::Version
33
- version: 0.10.0
62
+ version: 3.3.1
34
63
  type: :development
35
64
  prerelease: false
36
65
  version_requirements: !ruby/object:Gem::Requirement
37
66
  requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '3.3'
38
70
  - - ">="
39
71
  - !ruby/object:Gem::Version
40
- version: 0.10.0
72
+ version: 3.3.1
73
+ - !ruby/object:Gem::Dependency
74
+ name: rspec
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - "~>"
78
+ - !ruby/object:Gem::Version
79
+ version: '3.10'
80
+ type: :development
81
+ prerelease: false
82
+ version_requirements: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - "~>"
85
+ - !ruby/object:Gem::Version
86
+ version: '3.10'
87
+ - !ruby/object:Gem::Dependency
88
+ name: grape
89
+ requirement: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - "~>"
92
+ - !ruby/object:Gem::Version
93
+ version: '1.6'
94
+ type: :development
95
+ prerelease: false
96
+ version_requirements: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - "~>"
99
+ - !ruby/object:Gem::Version
100
+ version: '1.6'
41
101
  - !ruby/object:Gem::Dependency
42
102
  name: railties
43
103
  requirement: !ruby/object:Gem::Requirement
44
104
  requirements:
105
+ - - "~>"
106
+ - !ruby/object:Gem::Version
107
+ version: '6.1'
45
108
  - - ">="
46
109
  - !ruby/object:Gem::Version
47
- version: 5.0.0
110
+ version: 6.1.4.1
48
111
  type: :development
49
112
  prerelease: false
50
113
  version_requirements: !ruby/object:Gem::Requirement
51
114
  requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '6.1'
52
118
  - - ">="
53
119
  - !ruby/object:Gem::Version
54
- version: 5.0.0
120
+ version: 6.1.4.1
55
121
  - !ruby/object:Gem::Dependency
56
122
  name: actionpack
57
123
  requirement: !ruby/object:Gem::Requirement
58
124
  requirements:
125
+ - - "~>"
126
+ - !ruby/object:Gem::Version
127
+ version: '6.1'
59
128
  - - ">="
60
129
  - !ruby/object:Gem::Version
61
- version: 5.0.0
130
+ version: 6.1.4.1
62
131
  type: :development
63
132
  prerelease: false
64
133
  version_requirements: !ruby/object:Gem::Requirement
65
134
  requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: '6.1'
66
138
  - - ">="
67
139
  - !ruby/object:Gem::Version
68
- version: 5.0.0
140
+ version: 6.1.4.1
69
141
  - !ruby/object:Gem::Dependency
70
142
  name: sequel
71
143
  requirement: !ruby/object:Gem::Requirement
72
144
  requirements:
73
- - - ">="
145
+ - - "~>"
74
146
  - !ruby/object:Gem::Version
75
- version: 4.9.0
147
+ version: '5.49'
76
148
  type: :development
77
149
  prerelease: false
78
150
  version_requirements: !ruby/object:Gem::Requirement
79
151
  requirements:
80
- - - ">="
152
+ - - "~>"
153
+ - !ruby/object:Gem::Version
154
+ version: '5.49'
155
+ - !ruby/object:Gem::Dependency
156
+ name: activerecord-nulldb-adapter
157
+ requirement: !ruby/object:Gem::Requirement
158
+ requirements:
159
+ - - "~>"
81
160
  - !ruby/object:Gem::Version
82
- version: 4.9.0
161
+ version: 0.7.0
162
+ type: :development
163
+ prerelease: false
164
+ version_requirements: !ruby/object:Gem::Requirement
165
+ requirements:
166
+ - - "~>"
167
+ - !ruby/object:Gem::Version
168
+ version: 0.7.0
83
169
  description: Link header pagination for Rails and Grape APIs
84
170
  email:
85
171
  - me@davidcel.is
@@ -94,11 +180,14 @@ files:
94
180
  - lib/api-pagination/version.rb
95
181
  - lib/grape/pagination.rb
96
182
  - lib/rails/pagination.rb
183
+ - spec/active_record_spec.rb
97
184
  - spec/api-pagination_spec.rb
98
185
  - spec/grape_spec.rb
99
186
  - spec/rails_spec.rb
100
187
  - spec/sequel_spec.rb
101
188
  - spec/spec_helper.rb
189
+ - spec/support/active_record/foo.rb
190
+ - spec/support/active_record/schema.rb
102
191
  - spec/support/numbers_api.rb
103
192
  - spec/support/numbers_controller.rb
104
193
  - spec/support/shared_examples/existing_headers.rb
@@ -109,35 +198,37 @@ homepage: https://github.com/davidcelis/api-pagination
109
198
  licenses:
110
199
  - MIT
111
200
  metadata: {}
112
- post_install_message:
201
+ post_install_message:
113
202
  rdoc_options: []
114
203
  require_paths:
115
204
  - lib
116
205
  required_ruby_version: !ruby/object:Gem::Requirement
117
206
  requirements:
118
- - - ">="
207
+ - - ">"
119
208
  - !ruby/object:Gem::Version
120
- version: '0'
209
+ version: '2.7'
121
210
  required_rubygems_version: !ruby/object:Gem::Requirement
122
211
  requirements:
123
212
  - - ">="
124
213
  - !ruby/object:Gem::Version
125
214
  version: '0'
126
215
  requirements: []
127
- rubyforge_project:
128
- rubygems_version: 2.7.6
129
- signing_key:
216
+ rubygems_version: 3.2.22
217
+ signing_key:
130
218
  specification_version: 4
131
219
  summary: Link header pagination for Rails and Grape APIs. Don't use the request body.
132
220
  test_files:
133
- - spec/spec_helper.rb
221
+ - spec/active_record_spec.rb
134
222
  - spec/api-pagination_spec.rb
223
+ - spec/grape_spec.rb
224
+ - spec/rails_spec.rb
135
225
  - spec/sequel_spec.rb
226
+ - spec/spec_helper.rb
227
+ - spec/support/active_record/foo.rb
228
+ - spec/support/active_record/schema.rb
136
229
  - spec/support/numbers_api.rb
137
230
  - spec/support/numbers_controller.rb
231
+ - spec/support/shared_examples/existing_headers.rb
138
232
  - spec/support/shared_examples/first_page.rb
139
- - spec/support/shared_examples/middle_page.rb
140
233
  - spec/support/shared_examples/last_page.rb
141
- - spec/support/shared_examples/existing_headers.rb
142
- - spec/grape_spec.rb
143
- - spec/rails_spec.rb
234
+ - spec/support/shared_examples/middle_page.rb