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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: d8bd6ee617ad9ee01273cb7b36548cdb197110aa
4
- data.tar.gz: b24a83cb8d231b98d7ed1670adb7f23680a80210
2
+ SHA256:
3
+ metadata.gz: 0aeee41828ccf353b3be509b5ddc10f180cb238d9b12bb8c357dc3ddfd35f07e
4
+ data.tar.gz: d2e33f4bf383e78f99d9e0d5ee6878e6fa54c8f9ad7412de18d23cadf45ec650
5
5
  SHA512:
6
- metadata.gz: 729785a6c4835d934f1f6fdab6159ca54f2003aecb4368774581478bb40640b62b1790b332e9d567c2b02b55ae980bd37ae6b01b30fbf5288657f2c87e111cce
7
- data.tar.gz: aba98e01b6082d375864506e0ba1d6d6483961e6ef6d5bc61f8c4662fa81b6a785b5ca21029d237dead8e4a8aad28309c8f4c28e9be3924a53cd2eb00362e8c1
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
- @paginator || set_paginator
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
- if defined?(Kaminari) && defined?(WillPaginate::CollectionMethods)
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 either Kaminari or WillPaginate, but both are
70
- currently active. If possible, you should remove one or the other. If you can't,
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
- return use_kaminari
102
+ use_kaminari
88
103
  elsif defined?(WillPaginate::CollectionMethods)
89
- return use_will_paginate
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
@@ -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
- 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)
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. Please
25
- 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:
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
@@ -1,7 +1,7 @@
1
1
  module ApiPagination
2
2
  class Version
3
- MAJOR = 4
4
- MINOR = 4
3
+ MAJOR = 6
4
+ MINOR = 0
5
5
  PATCH = 0
6
6
 
7
7
  def self.to_s
@@ -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
- collection.paginate(:page => options[:page], :per_page => options[:per_page])
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
- detect_model(collection).default_per_page || default
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
- detect_model(collection).per_page || default
77
- rescue
78
- default
126
+ extract_per_page_from_model(collection, :per_page) || default
79
127
  end
80
128
 
81
- def detect_model(collection)
82
- collection.first.class
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
@@ -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 => Integer, :default => 1,
44
- :desc => 'Page of results to fetch.'
45
- optional :per_page, :type => Integer,
46
- :desc => 'Number of results to return per page.'
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
@@ -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
- links = (headers['Link'] || "").split(',').map(&:strip)
33
- url = request.original_url.sub(/\?.*$/, '')
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
+
@@ -1,30 +1,76 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe ApiPagination do
4
- let(:collection) { (1..100).to_a }
5
- let(:paginate_array_options) { { total_count: 1000 } }
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
- context 'Using kaminari' do
8
- before do
9
- ApiPagination.config.paginator = :kaminari
10
- end
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
- after do
13
- ApiPagination.config.paginator = ENV['PAGINATOR'].to_sym
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
- it 'should accept paginate_array_options option' do
17
- expect(Kaminari).to receive(:paginate_array)
18
- .with(collection, paginate_array_options)
19
- .and_call_original
20
-
21
- ApiPagination.paginate(
22
- collection,
23
- {
24
- per_page: 30,
25
- paginate_array_options: paginate_array_options
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(: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
 
@@ -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 'with a max_per_page setting' do
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(: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
 
15
16
  context 'without enough items to give more than one page' do
16
- before { get :index, :count => 10 }
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 => 30, :with_headers => true }
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 => 100 }
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 => 100, :page => 10 }
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 => 100, :page => 2 }
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 => 100
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, count: 10
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 => 2, :count => 100
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 => { :bar => 2 }, :count => 100
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 => 2, :count => 100
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 => { :bar => 2 }, :count => 100
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
- context 'paginate array options' do
205
- 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 }
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
- specify do
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
- context 'kaminari' do
220
- around do |example|
221
- paginator = ApiPagination.config.paginator
222
- ApiPagination.config.paginator = :kaminari
223
- example.run
224
- ApiPagination.config.paginator = paginator
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
- it_should_behave_like 'properly set Total header' do
228
- let(:paginate_array_total_count) { 300 }
229
- let(:total_header) { 300 }
230
- let(:count) { 50 }
252
+ class << self
253
+ attr_accessor :default_per_page, :per_page
254
+ end
255
+ end
231
256
  end
232
- end
233
257
 
234
- context 'will_paginate' do
235
- around do |example|
236
- paginator = ApiPagination.config.paginator
237
- ApiPagination.config.paginator = :will_paginate
238
- example.run
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
- it_should_behave_like 'properly set Total header' do
243
- let(:paginate_array_total_count) { 300 }
244
- let(:total_header) { 50 }
245
- 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
246
271
  end
247
- end
248
- end
249
272
 
250
- context 'default per page in model' do
251
- before do
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
- class << self
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
- after do
263
- class Fixnum
264
- @default_per_page = 25
265
- @per_page = 25
266
- end
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
- it 'should use default per page from model' do
270
- get :index_with_no_per_page, count: 100
285
+ get :index_with_no_per_page, params: {count: 100}
271
286
 
272
- 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[: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
- class Fixnum
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 '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
@@ -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, :max_per_page => 25
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::Base
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(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,165 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: api-pagination
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.4.0
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: 2016-09-13 00:00:00.000000000 Z
11
+ date: 2024-07-29 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: '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: 0.10.0
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: 0.10.0
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: 3.0.0
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: 3.0.0
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: 3.0.0
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: 3.0.0
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: 4.9.0
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: 4.9.0
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: '0'
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
- rubyforge_project:
127
- rubygems_version: 2.5.1
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