paging_cursor 0.1.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 +7 -0
- data/LICENSE +18 -0
- data/README.md +66 -0
- data/lib/paging_cursor.rb +7 -0
- data/lib/paging_cursor/active_record.rb +86 -0
- data/lib/paging_cursor/config.rb +31 -0
- data/lib/paging_cursor/direction.rb +26 -0
- data/spec/active_record_spec.rb +172 -0
- data/spec/array_spec.rb +21 -0
- data/spec/rails_helper.rb +13 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/support/models.rb +11 -0
- data/spec/support/schema.rb +14 -0
- metadata +111 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5a49f5abf6c5a0d96017ad40e05592dd78a208a4
|
4
|
+
data.tar.gz: 4df33eda9a444e83f823ecff325ae23450b6fbe2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1b9804935cd5836c327590b37402b4bac7e9eeeca41ffa10703bf237388358c657ad313db67a44266f642f89e0581966f1667781569c8d3085f9b0190b8a6f72
|
7
|
+
data.tar.gz: 783305c3f6a8dd815daa4b78d905fd396b2425a1e8367523891212a8ea313b3a722b7b5b9fe3fc06b9cb51215704d70944501f1368cfd65f21ade0f2d8321f5e
|
data/LICENSE
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Copyright (c) 2016 Rebecca "Becky" Segal
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
4
|
+
this software and associated documentation files (the "Software"), to deal in
|
5
|
+
the Software without restriction, including without limitation the rights to
|
6
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
7
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
8
|
+
subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
11
|
+
copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
15
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
16
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
17
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
18
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
# Usage
|
2
|
+
|
3
|
+
Use `.before`, `.after`, or `.cursor` in ActiveRecord queries to paginate data. A default limit is always applied, or you can override by including `.limit` in your request.
|
4
|
+
|
5
|
+
For example, say we have an app with User and Post models.
|
6
|
+
|
7
|
+
```
|
8
|
+
# app/models/user.rb
|
9
|
+
class User < ActiveRecord::Base
|
10
|
+
has_many :posts
|
11
|
+
end
|
12
|
+
|
13
|
+
# app/models/post.rb
|
14
|
+
class Post < ActiveRecord::Base
|
15
|
+
belongs_to :user
|
16
|
+
end
|
17
|
+
```
|
18
|
+
|
19
|
+
We can retrieve posts starting with the most recent
|
20
|
+
|
21
|
+
```
|
22
|
+
Post.before # get the first page of most recent posts with the default limit
|
23
|
+
Post.before.limit(10) # get the 10 most recent posts
|
24
|
+
Post.before(999).limit(10) # get the 10 most recent posts that were created before the post with id=999
|
25
|
+
Post.where(user: User.first).before(999) # get the 10 most recent posts meeting a condition
|
26
|
+
User.first.posts.before # get the most recent posts belong to a user
|
27
|
+
```
|
28
|
+
|
29
|
+
|
30
|
+
Likewise, we can results starting from the oldest records
|
31
|
+
|
32
|
+
```
|
33
|
+
Post.after # get the first page of oldest posts with the default limit
|
34
|
+
Post.after.limit(10) # get the 10 oldest posts
|
35
|
+
Post.after(999).limit(10) # get the 10 oldest posts that are newer than the post with id=999
|
36
|
+
Post.where(user: User.first).after(999) # get the 10 oldest posts meeting a condition
|
37
|
+
User.first.posts.after # get the oldest posts belong to a user
|
38
|
+
```
|
39
|
+
|
40
|
+
# Sorting results
|
41
|
+
|
42
|
+
By default, all results are returned in ascending order.
|
43
|
+
|
44
|
+
|
45
|
+
To customize, set a config option, class option or per-query option
|
46
|
+
|
47
|
+
|
48
|
+
# Adding pagination metadata to responses
|
49
|
+
|
50
|
+
This gem makes no assumptions about how you want to return pagination metadata in your responses. Arrays and results provide the cursor information you need.
|
51
|
+
|
52
|
+
```
|
53
|
+
result = Post.before(999)
|
54
|
+
result.length
|
55
|
+
=> 20
|
56
|
+
result.cursor_before
|
57
|
+
=> 990 # the minimum id included in the result
|
58
|
+
result.cursor_after
|
59
|
+
=> 998 # the maximum id included in the result
|
60
|
+
```
|
61
|
+
|
62
|
+
TODO
|
63
|
+
* option for sorting results
|
64
|
+
* cursor methods on array
|
65
|
+
* global default for limits
|
66
|
+
* per-model setting for limits
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
module PagingCursor
|
4
|
+
module ActiveRecord
|
5
|
+
|
6
|
+
# TODO: option to set which column is used for pagination
|
7
|
+
# default = :id
|
8
|
+
module FinderMethods
|
9
|
+
|
10
|
+
# default order = after
|
11
|
+
def cursor(options={})
|
12
|
+
options = HashWithIndifferentAccess.new(options)
|
13
|
+
if options.has_key?(:before) || (!options.has_key?(:after) && PagingCursor.config.default_sort_order == :desc)
|
14
|
+
result = before(options[:before])
|
15
|
+
else
|
16
|
+
result = after(options[:after])
|
17
|
+
end
|
18
|
+
result.limit(options[:limit] || self.cursor_page_limit)
|
19
|
+
end
|
20
|
+
|
21
|
+
def before(cursor=nil)
|
22
|
+
result = where(cursor ? arel_table[primary_key].lt(cursor) : nil).reorder(arel_table[primary_key].desc)
|
23
|
+
result.sort_order = :desc
|
24
|
+
result.cursored = true
|
25
|
+
result
|
26
|
+
end
|
27
|
+
|
28
|
+
def after(cursor=nil)
|
29
|
+
result = where(arel_table[primary_key].gt(cursor || 0)).reorder(arel_table[primary_key].asc)
|
30
|
+
result.sort_order = :asc
|
31
|
+
result.cursored = true
|
32
|
+
result
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
module Limit
|
37
|
+
attr_accessor :cursor_page_limit
|
38
|
+
|
39
|
+
# TODO: allow setting default at global and model levels
|
40
|
+
def initialize *a
|
41
|
+
self.default_page_limit = 25
|
42
|
+
super *a
|
43
|
+
end
|
44
|
+
|
45
|
+
def cursor_page_limit
|
46
|
+
@cursor_page_limit ||= PagingCursor.config.default_page_limit
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
module SortedResults
|
51
|
+
attr_accessor :sort_order, :cursored
|
52
|
+
|
53
|
+
def initialize *a
|
54
|
+
self.sort_order = :asc
|
55
|
+
self.cursored = false # todo, separate module??
|
56
|
+
super *a
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_a
|
60
|
+
return super unless self.cursored
|
61
|
+
r = ::PagingCursor::Array.new(super)
|
62
|
+
if self.sort_order != PagingCursor.config.default_sort_order.to_sym
|
63
|
+
r.reverse!
|
64
|
+
end
|
65
|
+
r
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
::ActiveRecord::Base.extend FinderMethods
|
70
|
+
::ActiveRecord::Base.extend Limit
|
71
|
+
|
72
|
+
klasses = [::ActiveRecord::Relation]
|
73
|
+
if defined? ::ActiveRecord::Associations::CollectionProxy
|
74
|
+
klasses << ::ActiveRecord::Associations::CollectionProxy
|
75
|
+
else
|
76
|
+
klasses << ::ActiveRecord::Associations::AssociationCollection
|
77
|
+
end
|
78
|
+
|
79
|
+
# # support pagination on associations and scopes
|
80
|
+
klasses.each do |klass|
|
81
|
+
klass.send(:prepend, SortedResults)
|
82
|
+
klass.send(:include, FinderMethods)
|
83
|
+
klass.send(:include, ::PagingCursor::Direction)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'active_support/configurable'
|
2
|
+
|
3
|
+
module PagingCursor
|
4
|
+
|
5
|
+
def self.configure(&block)
|
6
|
+
yield @config ||= PagingCursor::Configuration.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.config
|
10
|
+
@config
|
11
|
+
end
|
12
|
+
|
13
|
+
class Configuration
|
14
|
+
include ActiveSupport::Configurable
|
15
|
+
config_accessor :default_sort_order
|
16
|
+
config_accessor :default_page_limit
|
17
|
+
|
18
|
+
def param_name
|
19
|
+
config.param_name.respond_to?(:call) ? config.param_name.call : config.param_name
|
20
|
+
end
|
21
|
+
|
22
|
+
writer, line = 'def param_name=(value); config.param_name = value; end', __LINE__
|
23
|
+
singleton_class.class_eval writer, __FILE__, line
|
24
|
+
class_eval writer, __FILE__, line
|
25
|
+
end
|
26
|
+
|
27
|
+
configure do |config|
|
28
|
+
config.default_sort_order = :asc
|
29
|
+
config.default_page_limit = 25
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module PagingCursor
|
2
|
+
module Direction
|
3
|
+
|
4
|
+
# TODO: *terrible* shouldn't need to cast to array to ensure sort order
|
5
|
+
# def first(limit = nil)
|
6
|
+
# limit.nil? ? to_a.first : super
|
7
|
+
# end
|
8
|
+
|
9
|
+
# def last(limit = nil)
|
10
|
+
# limit.nil? ? to_a.last : super
|
11
|
+
# end
|
12
|
+
|
13
|
+
def cursor_before
|
14
|
+
self.collect(&:id).min
|
15
|
+
end
|
16
|
+
|
17
|
+
def cursor_after
|
18
|
+
self.collect(&:id).max
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class Array < ::Array
|
23
|
+
end
|
24
|
+
|
25
|
+
Array.include Direction
|
26
|
+
end
|
@@ -0,0 +1,172 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
describe 'finders' do
|
4
|
+
shared_examples_for 'the first 5 posts' do
|
5
|
+
specify { expect(result).to eq(Post.first(5)) }
|
6
|
+
end
|
7
|
+
|
8
|
+
shared_examples_for 'the last 5 posts' do
|
9
|
+
specify { expect(result).to eq(Post.last(5))}
|
10
|
+
end
|
11
|
+
|
12
|
+
shared_examples_for 'the first 5 posts after 2' do
|
13
|
+
specify { expect(result.collect(&:id)).to eq((@min+2 .. @min+6).to_a) }
|
14
|
+
end
|
15
|
+
|
16
|
+
shared_examples_for 'the last 5 posts except 2' do
|
17
|
+
specify { expect(result.collect(&:id)).to eq((@max-6 .. @max-2).to_a) }
|
18
|
+
end
|
19
|
+
|
20
|
+
before do
|
21
|
+
PagingCursor.config.default_sort_order = :asc
|
22
|
+
@user = User.create
|
23
|
+
10.times do
|
24
|
+
Post.create(user_id: @user.id)
|
25
|
+
end
|
26
|
+
@min = Post.first.id
|
27
|
+
@max = Post.last.id
|
28
|
+
end
|
29
|
+
|
30
|
+
after do
|
31
|
+
Post.delete_all
|
32
|
+
User.delete_all
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'accepts the limit parameter through cursor' do
|
36
|
+
expect(Post.cursor(limit: 2).size).to eq(2)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'accepts string and symbol eys' do
|
40
|
+
expect(Post.cursor('limit' => 2)).to eq(Post.cursor(limit: 2))
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'does not override limit() with cursor option' do
|
44
|
+
expect(Post.cursor(limit: 2).limit(8).size).to eq(8)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'returns a PagingCursor::Array' do
|
48
|
+
expect(Post.after.to_a.class).to be(PagingCursor::Array)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'respects configured desc sort order' do
|
52
|
+
PagingCursor.config.default_sort_order = :desc
|
53
|
+
after = Post.after
|
54
|
+
before = Post.before
|
55
|
+
cursor = Post.cursor
|
56
|
+
expect(after[0].id).to be > after[1].id
|
57
|
+
expect(before[0].id).to be > before[1].id
|
58
|
+
expect(cursor[0].id).to be > cursor[1].id
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'respects configured asc sort order' do
|
62
|
+
PagingCursor.config.default_sort_order = :asc
|
63
|
+
after = Post.after
|
64
|
+
before = Post.before
|
65
|
+
cursor = Post.cursor
|
66
|
+
expect(after[1].id).to be > after[0].id
|
67
|
+
expect(before[1].id).to be > before[0].id
|
68
|
+
expect(cursor[1].id).to be > cursor[0].id
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'on active record' do
|
72
|
+
it_behaves_like "the first 5 posts" do
|
73
|
+
let(:result) { Post.after.limit(5) }
|
74
|
+
end
|
75
|
+
|
76
|
+
it_behaves_like "the last 5 posts" do
|
77
|
+
let(:result) { Post.before.limit(5) }
|
78
|
+
end
|
79
|
+
|
80
|
+
it_behaves_like "the first 5 posts after 2" do
|
81
|
+
let(:result) { Post.after(@min + 1).limit(5) }
|
82
|
+
end
|
83
|
+
|
84
|
+
it_behaves_like "the last 5 posts except 2" do
|
85
|
+
let(:result) { Post.before(@max-1).limit(5) }
|
86
|
+
end
|
87
|
+
|
88
|
+
it_behaves_like "the first 5 posts" do
|
89
|
+
let(:result) { Post.cursor(after: nil).limit(5) }
|
90
|
+
end
|
91
|
+
|
92
|
+
it_behaves_like "the last 5 posts" do
|
93
|
+
let(:result) { Post.cursor(before: nil).limit(5) }
|
94
|
+
end
|
95
|
+
|
96
|
+
it_behaves_like "the first 5 posts after 2" do
|
97
|
+
let(:result) { Post.cursor(after: @min + 1).limit(5) }
|
98
|
+
end
|
99
|
+
|
100
|
+
it_behaves_like "the last 5 posts except 2" do
|
101
|
+
let(:result) { Post.cursor(before: @max-1).limit(5) }
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
context 'on relations' do
|
106
|
+
it_behaves_like "the first 5 posts" do
|
107
|
+
let(:result) { Post.where(user_id: @user.id).after.limit(5) }
|
108
|
+
end
|
109
|
+
|
110
|
+
it_behaves_like "the last 5 posts" do
|
111
|
+
let(:result) { Post.where(user_id: @user.id).before.limit(5) }
|
112
|
+
end
|
113
|
+
|
114
|
+
it_behaves_like "the first 5 posts after 2" do
|
115
|
+
let(:result) { Post.where(user_id: @user.id).after(@min + 1).limit(5) }
|
116
|
+
end
|
117
|
+
|
118
|
+
it_behaves_like "the last 5 posts except 2" do
|
119
|
+
let(:result) { Post.where(user_id: @user.id).before(@max - 1).limit(5) }
|
120
|
+
end
|
121
|
+
|
122
|
+
it_behaves_like "the first 5 posts" do
|
123
|
+
let(:result) { Post.where(user_id: @user.id).cursor(after: nil).limit(5) }
|
124
|
+
end
|
125
|
+
|
126
|
+
it_behaves_like "the last 5 posts" do
|
127
|
+
let(:result) { Post.where(user_id: @user.id).cursor(before: nil).limit(5) }
|
128
|
+
end
|
129
|
+
|
130
|
+
it_behaves_like "the first 5 posts after 2" do
|
131
|
+
let(:result) { Post.where(user_id: @user.id).cursor(after: @min + 1).limit(5) }
|
132
|
+
end
|
133
|
+
|
134
|
+
it_behaves_like "the last 5 posts except 2" do
|
135
|
+
let(:result) { Post.where(user_id: @user.id).cursor(before: @max-1).limit(5) }
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
context 'on associations' do
|
140
|
+
it_behaves_like "the first 5 posts" do
|
141
|
+
let(:result) { @user.posts.after.limit(5) }
|
142
|
+
end
|
143
|
+
|
144
|
+
it_behaves_like "the last 5 posts" do
|
145
|
+
let(:result) { @user.posts.before.limit(5) }
|
146
|
+
end
|
147
|
+
|
148
|
+
it_behaves_like "the first 5 posts after 2" do
|
149
|
+
let(:result) { @user.posts.after(@min + 1).limit(5) }
|
150
|
+
end
|
151
|
+
|
152
|
+
it_behaves_like "the last 5 posts except 2" do
|
153
|
+
let(:result) { @user.posts.before(@max - 1).limit(5) }
|
154
|
+
end
|
155
|
+
|
156
|
+
it_behaves_like "the first 5 posts" do
|
157
|
+
let(:result) { @user.posts.cursor(after: nil).limit(5) }
|
158
|
+
end
|
159
|
+
|
160
|
+
it_behaves_like "the last 5 posts" do
|
161
|
+
let(:result) { @user.posts.cursor(before: nil).limit(5) }
|
162
|
+
end
|
163
|
+
|
164
|
+
it_behaves_like "the first 5 posts after 2" do
|
165
|
+
let(:result) { @user.posts.cursor(after: @min + 1).limit(5) }
|
166
|
+
end
|
167
|
+
|
168
|
+
it_behaves_like "the last 5 posts except 2" do
|
169
|
+
let(:result) { @user.posts.cursor(before: @max - 1).limit(5) }
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
data/spec/array_spec.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
describe PagingCursor::Array do
|
4
|
+
it "adds before and after cursors" do
|
5
|
+
a = PagingCursor::Array.new([u1=User.create, u2=User.create])
|
6
|
+
expect(a.cursor_before).to eq(u1.id)
|
7
|
+
expect(a.cursor_after).to eq(u2.id)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "adds correct cursors when array is not sorted" do
|
11
|
+
a = PagingCursor::Array.new([u1=User.create, u2=User.create].reverse)
|
12
|
+
expect(a.cursor_before).to eq(u1.id)
|
13
|
+
expect(a.cursor_after).to eq(u2.id)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "adds cursors for non-id primary key columns" do
|
17
|
+
a = PagingCursor::Array.new([t1=Tag.create, t2=Tag.create])
|
18
|
+
expect(a.cursor_before).to eq(t1.name)
|
19
|
+
expect(a.cursor_after).to eq(t2.name)
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
ENV['RAILS_ENV'] ||= 'test'
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'rails/all'
|
5
|
+
require 'rspec/rails'
|
6
|
+
ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
|
7
|
+
|
8
|
+
load File.dirname(__FILE__) + '/support/schema.rb'
|
9
|
+
require File.dirname(__FILE__) + '/support/models.rb'
|
10
|
+
|
11
|
+
RSpec.configure do |config|
|
12
|
+
|
13
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
ActiveRecord::Schema.define do
|
2
|
+
self.verbose = false
|
3
|
+
|
4
|
+
create_table :users, force: true do |t|
|
5
|
+
end
|
6
|
+
|
7
|
+
create_table :posts, force: true do |t|
|
8
|
+
t.integer :user_id
|
9
|
+
end
|
10
|
+
|
11
|
+
create_table :tags, force: true, id: false do |t|
|
12
|
+
t.string :name, primary_key: true
|
13
|
+
end
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: paging_cursor
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Becky Segal
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-04-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rails
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 4.0.0
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 4.0.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: sqlite3
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec-rails
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: ActiveRecord and ActiveController extensions for cursor pagination
|
70
|
+
email: becsegal@gmail.com
|
71
|
+
executables: []
|
72
|
+
extensions: []
|
73
|
+
extra_rdoc_files: []
|
74
|
+
files:
|
75
|
+
- LICENSE
|
76
|
+
- README.md
|
77
|
+
- lib/paging_cursor.rb
|
78
|
+
- lib/paging_cursor/active_record.rb
|
79
|
+
- lib/paging_cursor/config.rb
|
80
|
+
- lib/paging_cursor/direction.rb
|
81
|
+
- spec/active_record_spec.rb
|
82
|
+
- spec/array_spec.rb
|
83
|
+
- spec/rails_helper.rb
|
84
|
+
- spec/spec_helper.rb
|
85
|
+
- spec/support/models.rb
|
86
|
+
- spec/support/schema.rb
|
87
|
+
homepage:
|
88
|
+
licenses:
|
89
|
+
- MIT
|
90
|
+
metadata: {}
|
91
|
+
post_install_message:
|
92
|
+
rdoc_options: []
|
93
|
+
require_paths:
|
94
|
+
- lib
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
requirements: []
|
106
|
+
rubyforge_project:
|
107
|
+
rubygems_version: 2.4.6
|
108
|
+
signing_key:
|
109
|
+
specification_version: 4
|
110
|
+
summary: ActiveRecord and ActiveController extensions for cursor pagination
|
111
|
+
test_files: []
|