activerecord_cursor_paginate 0.2.0 → 0.4.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 +4 -4
- data/CHANGELOG.md +33 -0
- data/README.md +9 -2
- data/lib/activerecord_cursor_paginate/cursor.rb +11 -6
- data/lib/activerecord_cursor_paginate/extension.rb +2 -3
- data/lib/activerecord_cursor_paginate/page.rb +4 -3
- data/lib/activerecord_cursor_paginate/paginator.rb +177 -53
- data/lib/activerecord_cursor_paginate/version.rb +1 -1
- data/lib/activerecord_cursor_paginate.rb +3 -0
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c62461c4c0310350845f94c41ac762fc39e55892471c3b3f27482000ce2573fb
|
4
|
+
data.tar.gz: 0cc0e0d561bedeac454bcec204b56e7b2cb85bf84e0785ed50862753604c60f3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4a2b046f6ee4792539aea7b84fc3a0e65994c39d0f1d14f58cb2d3e57b39a9f4181b61c66dc5bd90462a16fbd6f6b351fbef653189d6c264c543d16c53ee7ca1
|
7
|
+
data.tar.gz: 74ab23173240984e9296544ad760172878d14b4d22cd4d01857f362d36220e90e530fe488933ba0fe29fd46ccff9ae909bac35d28323cbc615964492ea3e6096
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,38 @@
|
|
1
1
|
## master (unreleased)
|
2
2
|
|
3
|
+
## 0.4.0 (2025-03-10)
|
4
|
+
|
5
|
+
- Add ability to paginate backward from the end of the collection
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
paginator = users.cursor_paginate(forward_pagination: false)
|
9
|
+
```
|
10
|
+
|
11
|
+
## 0.3.0 (2025-01-06)
|
12
|
+
|
13
|
+
- Allow paginating over nullable columns
|
14
|
+
|
15
|
+
Previously, the error was raised when cursor values contained `nil`s. Now, it is possible to paginate
|
16
|
+
over columns containing `nil` values. You need to explicitly configure which columns are nullable,
|
17
|
+
otherwise columns are considered as non-nullable by the gem.
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
paginator = users.cursor_paginate(order: [:name, :id], nullable_columns: [:name])
|
21
|
+
```
|
22
|
+
|
23
|
+
Note that it is not recommended to use this feature, because the complexity of produced SQL queries can have
|
24
|
+
a very negative impact on the database performance. It is better to paginate using only non-nullable columns.
|
25
|
+
|
26
|
+
- Fix paginating over relations with joins, includes and custom ordering
|
27
|
+
- Add ability to incrementally configure a paginator
|
28
|
+
|
29
|
+
- Add ability to get the total number of records
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
paginator = posts.cursor_paginate
|
33
|
+
paginator.total_count # => 145
|
34
|
+
```
|
35
|
+
|
3
36
|
## 0.2.0 (2024-05-23)
|
4
37
|
|
5
38
|
- Fix prefixing selected columns when iterating over joined tables
|
data/README.md
CHANGED
@@ -8,7 +8,7 @@ Where a regular limit / offset pagination would jump in results if a record on a
|
|
8
8
|
|
9
9
|
To learn more about cursor pagination, check out the _"How does it work?"_ section below.
|
10
10
|
|
11
|
-
[](https://github.com/healthie/activerecord_cursor_paginate/actions/workflows/test.yml)
|
12
12
|
|
13
13
|
## Requirements
|
14
14
|
|
@@ -44,9 +44,16 @@ And then we create our paginator to fetch the first response page:
|
|
44
44
|
|
45
45
|
```ruby
|
46
46
|
paginator = posts.cursor_paginate
|
47
|
+
|
48
|
+
# Total number of records to iterate by this paginator
|
49
|
+
paginator.total_count # => 145
|
50
|
+
|
47
51
|
page = paginator.fetch
|
48
52
|
page.records # => [#<Post:0x00007fd7071b2ea8 @id=1>, #<Post:0x00007fd7071bb738 @id=2>, ..., #<Post:0x00007fd707238260 @id=10>]
|
53
|
+
|
54
|
+
# Number of records in this page
|
49
55
|
page.count # => 10
|
56
|
+
|
50
57
|
page.empty? # => false
|
51
58
|
page.cursors # => ["MQ", "Mg", ..., "MTA"]
|
52
59
|
| |
|
@@ -375,7 +382,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
375
382
|
|
376
383
|
## Contributing
|
377
384
|
|
378
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
385
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/healthie/activerecord_cursor_paginate.
|
379
386
|
|
380
387
|
## License
|
381
388
|
|
@@ -7,12 +7,12 @@ module ActiveRecordCursorPaginate
|
|
7
7
|
# @private
|
8
8
|
class Cursor
|
9
9
|
class << self
|
10
|
-
def from_record(record, columns:)
|
10
|
+
def from_record(record, columns:, nullable_columns: nil)
|
11
11
|
values = columns.map { |column| record[column] }
|
12
|
-
new(columns: columns, values: values)
|
12
|
+
new(columns: columns, values: values, nullable_columns: nullable_columns)
|
13
13
|
end
|
14
14
|
|
15
|
-
def decode(cursor_string:, columns:)
|
15
|
+
def decode(cursor_string:, columns:, nullable_columns: nil)
|
16
16
|
decoded = JSON.parse(Base64.urlsafe_decode64(cursor_string))
|
17
17
|
|
18
18
|
if (columns.size == 1 && decoded.is_a?(Array)) ||
|
@@ -28,7 +28,7 @@ module ActiveRecordCursorPaginate
|
|
28
28
|
deserialize_time_if_needed(decoded)
|
29
29
|
end
|
30
30
|
|
31
|
-
new(columns: columns, values: decoded)
|
31
|
+
new(columns: columns, values: decoded, nullable_columns: nullable_columns)
|
32
32
|
rescue ArgumentError, JSON::ParserError # ArgumentError is raised by strict_decode64
|
33
33
|
raise InvalidCursorError, "The given cursor `#{cursor_string}` could not be decoded"
|
34
34
|
end
|
@@ -46,11 +46,16 @@ module ActiveRecordCursorPaginate
|
|
46
46
|
|
47
47
|
attr_reader :columns, :values
|
48
48
|
|
49
|
-
def initialize(columns:, values:)
|
49
|
+
def initialize(columns:, values:, nullable_columns: nil)
|
50
50
|
@columns = Array.wrap(columns)
|
51
51
|
@values = Array.wrap(values)
|
52
|
+
@nullable_columns = Array.wrap(nullable_columns)
|
53
|
+
|
54
|
+
nil_index = @values.index(nil)
|
55
|
+
if nil_index && !@nullable_columns.include?(@columns[nil_index])
|
56
|
+
raise ArgumentError, "Cursor value is nil for a column that is not in the :nullable_columns list"
|
57
|
+
end
|
52
58
|
|
53
|
-
raise ArgumentError, "Cursor values can not be nil" if @values.any?(nil)
|
54
59
|
raise ArgumentError, ":columns and :values have different sizes" if @columns.size != @values.size
|
55
60
|
end
|
56
61
|
|
@@ -10,9 +10,8 @@ module ActiveRecordCursorPaginate
|
|
10
10
|
# paginator = Post.cursor_paginate(limit: 2, after: "Mg")
|
11
11
|
# page = paginator.fetch
|
12
12
|
#
|
13
|
-
def cursor_paginate(
|
14
|
-
|
15
|
-
Paginator.new(relation, after: after, before: before, limit: limit, order: order, append_primary_key: append_primary_key)
|
13
|
+
def cursor_paginate(**options)
|
14
|
+
Paginator.new(all, **options)
|
16
15
|
end
|
17
16
|
alias cursor_pagination cursor_paginate
|
18
17
|
end
|
@@ -6,15 +6,16 @@ module ActiveRecordCursorPaginate
|
|
6
6
|
#
|
7
7
|
class Page
|
8
8
|
# Records this page contains.
|
9
|
-
# @return [ActiveRecord::Base]
|
9
|
+
# @return [Array<ActiveRecord::Base>]
|
10
10
|
#
|
11
11
|
attr_reader :records
|
12
12
|
|
13
|
-
def initialize(records, order_columns:, has_previous: false, has_next: false)
|
13
|
+
def initialize(records, order_columns:, has_previous: false, has_next: false, nullable_columns: nil)
|
14
14
|
@records = records
|
15
15
|
@order_columns = order_columns
|
16
16
|
@has_previous = has_previous
|
17
17
|
@has_next = has_next
|
18
|
+
@nullable_columns = nullable_columns
|
18
19
|
end
|
19
20
|
|
20
21
|
# Number of records in this page.
|
@@ -79,7 +80,7 @@ module ActiveRecordCursorPaginate
|
|
79
80
|
private
|
80
81
|
def cursor_for_record(record)
|
81
82
|
if record
|
82
|
-
cursor = Cursor.from_record(record, columns: @order_columns)
|
83
|
+
cursor = Cursor.from_record(record, columns: @order_columns, nullable_columns: @nullable_columns)
|
83
84
|
cursor.encode
|
84
85
|
end
|
85
86
|
end
|
@@ -19,6 +19,9 @@ module ActiveRecordCursorPaginate
|
|
19
19
|
# end
|
20
20
|
#
|
21
21
|
class Paginator
|
22
|
+
attr_reader :relation, :before, :after, :limit, :order, :append_primary_key
|
23
|
+
attr_accessor :forward_pagination
|
24
|
+
|
22
25
|
# Create a new instance of the `ActiveRecordCursorPaginate::Paginator`
|
23
26
|
#
|
24
27
|
# @param relation [ActiveRecord::Relation] Relation that will be paginated.
|
@@ -38,30 +41,92 @@ module ActiveRecordCursorPaginate
|
|
38
41
|
# should be implicitly appended to the list of sorting columns. It may be useful
|
39
42
|
# to disable it for the table with a UUID primary key or when the sorting is done by a
|
40
43
|
# combination of columns that are already unique.
|
44
|
+
# @param nullable_columns [Symbol, String, nil, Array] Columns which are nullable.
|
45
|
+
# By default, all columns are considered as non-nullable, if not in this list.
|
46
|
+
# It is not recommended to use this feature, because the complexity of produced SQL
|
47
|
+
# queries can have a very negative impact on the database performance. It is better
|
48
|
+
# to paginate using only non-nullable columns.
|
49
|
+
# @param forward_pagination [Boolean] Whether this is a forward or backward pagination.
|
50
|
+
# Optional, defaults to `true` if `:before` is not provided, `false` otherwise.
|
51
|
+
# Useful when paginating backward from the end of the collection.
|
52
|
+
#
|
41
53
|
# @raise [ArgumentError] If any parameter is not valid
|
42
54
|
#
|
43
|
-
def initialize(relation, before: nil, after: nil, limit: nil, order: nil, append_primary_key: true
|
55
|
+
def initialize(relation, before: nil, after: nil, limit: nil, order: nil, append_primary_key: true,
|
56
|
+
nullable_columns: nil, forward_pagination: before.nil?)
|
44
57
|
unless relation.is_a?(ActiveRecord::Relation)
|
45
58
|
raise ArgumentError, "relation is not an ActiveRecord::Relation"
|
46
59
|
end
|
47
60
|
|
48
|
-
|
61
|
+
@relation = relation
|
62
|
+
@primary_key = @relation.primary_key
|
63
|
+
@append_primary_key = append_primary_key
|
64
|
+
|
65
|
+
@cursor = @current_cursor = nil
|
66
|
+
@forward_pagination = forward_pagination
|
67
|
+
@before = @after = nil
|
68
|
+
@page_size = nil
|
69
|
+
@limit = nil
|
70
|
+
@columns = []
|
71
|
+
@directions = []
|
72
|
+
@order = nil
|
73
|
+
|
74
|
+
self.before = before
|
75
|
+
self.after = after
|
76
|
+
self.limit = limit
|
77
|
+
self.order = order
|
78
|
+
self.nullable_columns = nullable_columns
|
79
|
+
end
|
80
|
+
|
81
|
+
def before=(value)
|
82
|
+
if value.present? && after.present?
|
83
|
+
raise ArgumentError, "Only one of :before and :after can be provided"
|
84
|
+
end
|
85
|
+
|
86
|
+
@cursor = value || after
|
87
|
+
@current_cursor = @cursor
|
88
|
+
@forward_pagination = false if value
|
89
|
+
@before = value
|
90
|
+
end
|
91
|
+
|
92
|
+
def after=(value)
|
93
|
+
if value.present? && before.present?
|
49
94
|
raise ArgumentError, "Only one of :before and :after can be provided"
|
50
95
|
end
|
51
96
|
|
52
|
-
@
|
53
|
-
@
|
54
|
-
@
|
55
|
-
@
|
97
|
+
@cursor = value || before
|
98
|
+
@current_cursor = @cursor
|
99
|
+
@forward_pagination = true if value
|
100
|
+
@after = value
|
101
|
+
end
|
56
102
|
|
103
|
+
def limit=(value)
|
57
104
|
config = ActiveRecordCursorPaginate.config
|
58
|
-
@page_size =
|
105
|
+
@page_size = value || config.default_page_size
|
59
106
|
@page_size = [@page_size, config.max_page_size].min if config.max_page_size
|
107
|
+
@limit = value
|
108
|
+
end
|
60
109
|
|
61
|
-
|
62
|
-
order = normalize_order(
|
110
|
+
def order=(value)
|
111
|
+
order = normalize_order(value)
|
63
112
|
@columns = order.keys
|
64
113
|
@directions = order.values
|
114
|
+
@order = value
|
115
|
+
end
|
116
|
+
|
117
|
+
def nullable_columns=(value)
|
118
|
+
value = Array.wrap(value)
|
119
|
+
value = value.map { |column| column.is_a?(Symbol) ? column.to_s : column }
|
120
|
+
|
121
|
+
if (value - @columns).any?
|
122
|
+
raise ArgumentError, ":nullable_columns should include only column names from the :order option"
|
123
|
+
end
|
124
|
+
|
125
|
+
if value.include?(@columns.last)
|
126
|
+
raise ArgumentError, "Last order column can not be nullable"
|
127
|
+
end
|
128
|
+
|
129
|
+
@nullable_columns = value
|
65
130
|
end
|
66
131
|
|
67
132
|
# Get the paginated result.
|
@@ -70,45 +135,20 @@ module ActiveRecordCursorPaginate
|
|
70
135
|
# @note Calling this method advances the paginator.
|
71
136
|
#
|
72
137
|
def fetch
|
73
|
-
relation = @
|
74
|
-
|
75
|
-
# Non trivial columns (expressions or joined tables columns).
|
76
|
-
if @columns.any?(/\W/)
|
77
|
-
arel_columns = @columns.map.with_index do |column, i|
|
78
|
-
arel_column(column).as("cursor_column_#{i + 1}")
|
79
|
-
end
|
80
|
-
cursor_column_names = arel_columns.map { |column| column.right.to_s }
|
81
|
-
|
82
|
-
relation =
|
83
|
-
if relation.select_values.empty?
|
84
|
-
relation.select(relation.arel_table[Arel.star], arel_columns)
|
85
|
-
else
|
86
|
-
relation.select(arel_columns)
|
87
|
-
end
|
88
|
-
else
|
89
|
-
cursor_column_names = @columns
|
90
|
-
end
|
91
|
-
|
92
|
-
pagination_directions = @directions.map { |direction| pagination_direction(direction) }
|
93
|
-
relation = relation.reorder(cursor_column_names.zip(pagination_directions).to_h)
|
94
|
-
|
95
|
-
if @cursor
|
96
|
-
decoded_cursor = Cursor.decode(cursor_string: @cursor, columns: @columns)
|
97
|
-
relation = apply_cursor(relation, decoded_cursor)
|
98
|
-
end
|
138
|
+
relation = build_cursor_relation(@current_cursor)
|
99
139
|
|
100
140
|
relation = relation.limit(@page_size + 1)
|
101
141
|
records_plus_one = relation.to_a
|
102
142
|
has_additional = records_plus_one.size > @page_size
|
103
143
|
|
104
144
|
records = records_plus_one.take(@page_size)
|
105
|
-
records.reverse! unless @
|
145
|
+
records.reverse! unless @forward_pagination
|
106
146
|
|
107
|
-
if @
|
147
|
+
if @forward_pagination
|
108
148
|
has_next_page = has_additional
|
109
|
-
has_previous_page = @
|
149
|
+
has_previous_page = @current_cursor.present?
|
110
150
|
else
|
111
|
-
has_next_page = @
|
151
|
+
has_next_page = @current_cursor.present?
|
112
152
|
has_previous_page = has_additional
|
113
153
|
end
|
114
154
|
|
@@ -116,7 +156,8 @@ module ActiveRecordCursorPaginate
|
|
116
156
|
records,
|
117
157
|
order_columns: cursor_column_names,
|
118
158
|
has_next: has_next_page,
|
119
|
-
has_previous: has_previous_page
|
159
|
+
has_previous: has_previous_page,
|
160
|
+
nullable_columns: nullable_cursor_column_names
|
120
161
|
)
|
121
162
|
|
122
163
|
advance_by_page(page) unless page.empty?
|
@@ -139,6 +180,13 @@ module ActiveRecordCursorPaginate
|
|
139
180
|
end
|
140
181
|
end
|
141
182
|
|
183
|
+
# Total number of records to iterate by this paginator.
|
184
|
+
# @return [Integer]
|
185
|
+
#
|
186
|
+
def total_count
|
187
|
+
@total_count ||= build_cursor_relation(@cursor).count(:all)
|
188
|
+
end
|
189
|
+
|
142
190
|
private
|
143
191
|
def normalize_order(order)
|
144
192
|
order ||= {}
|
@@ -168,20 +216,81 @@ module ActiveRecordCursorPaginate
|
|
168
216
|
result
|
169
217
|
end
|
170
218
|
|
219
|
+
def build_cursor_relation(cursor)
|
220
|
+
relation = @relation
|
221
|
+
|
222
|
+
# Non trivial columns (expressions or joined tables columns).
|
223
|
+
if @columns.any?(/\W/)
|
224
|
+
arel_columns = @columns.map.with_index do |column, i|
|
225
|
+
arel_column(column).as("cursor_column_#{i + 1}")
|
226
|
+
end
|
227
|
+
|
228
|
+
relation =
|
229
|
+
if relation.select_values.empty?
|
230
|
+
relation.select(relation.arel_table[Arel.star], arel_columns)
|
231
|
+
else
|
232
|
+
relation.select(arel_columns)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
pagination_directions = @directions.map { |direction| pagination_direction(direction) }
|
237
|
+
relation = relation.reorder(@columns.zip(pagination_directions).to_h)
|
238
|
+
|
239
|
+
if cursor
|
240
|
+
decoded_cursor = Cursor.decode(cursor_string: cursor, columns: cursor_column_names, nullable_columns: nullable_cursor_column_names)
|
241
|
+
relation = apply_cursor(relation, decoded_cursor)
|
242
|
+
end
|
243
|
+
|
244
|
+
relation
|
245
|
+
end
|
246
|
+
|
247
|
+
def nullable_cursor_column_names
|
248
|
+
@nullable_columns.map do |column|
|
249
|
+
cursor_column_names[@columns.index(column)]
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
def cursor_column_names
|
254
|
+
if @columns.any?(/\W/)
|
255
|
+
@columns.size.times.map { |i| "cursor_column_#{i + 1}" }
|
256
|
+
else
|
257
|
+
@columns
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
171
261
|
def apply_cursor(relation, cursor)
|
172
|
-
|
173
|
-
cursor_positions = cursor.columns.zip(cursor.values, operators)
|
262
|
+
cursor_positions = @columns.zip(cursor.values, @directions)
|
174
263
|
|
175
264
|
where_clause = nil
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
265
|
+
|
266
|
+
cursor_positions.reverse_each.with_index do |(column, value, direction), index|
|
267
|
+
previous_where_clause = where_clause
|
268
|
+
|
269
|
+
operator = pagination_operator(direction)
|
270
|
+
arel_column = arel_column(column)
|
271
|
+
|
272
|
+
# The last column can't be nil.
|
273
|
+
if index == 0
|
274
|
+
where_clause = arel_column.public_send(operator, value)
|
275
|
+
elsif value.nil?
|
276
|
+
if nulls_at_end?(direction)
|
277
|
+
# We are at the section with nulls, which is at the end ([x, x, null, null, null])
|
278
|
+
where_clause = arel_column.eq(nil).and(previous_where_clause)
|
180
279
|
else
|
181
|
-
|
182
|
-
|
183
|
-
)
|
280
|
+
# We are at the section with nulls, which is at the beginning ([null, null, null, x, x])
|
281
|
+
where_clause = arel_column.not_eq(nil)
|
282
|
+
where_clause = arel_column.eq(nil).and(previous_where_clause).or(where_clause)
|
184
283
|
end
|
284
|
+
else
|
285
|
+
where_clause = arel_column.public_send(operator, value).or(
|
286
|
+
arel_column.eq(value).and(previous_where_clause)
|
287
|
+
)
|
288
|
+
|
289
|
+
if nullable_column?(column) && nulls_at_end?(direction)
|
290
|
+
# Since column's value is not null, nulls can only be at the end.
|
291
|
+
where_clause = arel_column.eq(nil).or(where_clause)
|
292
|
+
end
|
293
|
+
end
|
185
294
|
end
|
186
295
|
|
187
296
|
relation.where(where_clause)
|
@@ -198,7 +307,7 @@ module ActiveRecordCursorPaginate
|
|
198
307
|
end
|
199
308
|
|
200
309
|
def pagination_direction(direction)
|
201
|
-
if @
|
310
|
+
if @forward_pagination
|
202
311
|
direction
|
203
312
|
else
|
204
313
|
direction == :asc ? :desc : :asc
|
@@ -206,7 +315,7 @@ module ActiveRecordCursorPaginate
|
|
206
315
|
end
|
207
316
|
|
208
317
|
def pagination_operator(direction)
|
209
|
-
if @
|
318
|
+
if @forward_pagination
|
210
319
|
direction == :asc ? :gt : :lt
|
211
320
|
else
|
212
321
|
direction == :asc ? :lt : :gt
|
@@ -214,12 +323,27 @@ module ActiveRecordCursorPaginate
|
|
214
323
|
end
|
215
324
|
|
216
325
|
def advance_by_page(page)
|
217
|
-
@
|
218
|
-
if @
|
326
|
+
@current_cursor =
|
327
|
+
if @forward_pagination
|
219
328
|
page.next_cursor
|
220
329
|
else
|
221
330
|
page.previous_cursor
|
222
331
|
end
|
223
332
|
end
|
333
|
+
|
334
|
+
def nulls_at_end?(direction)
|
335
|
+
(direction == :asc && !small_nulls?) || (direction == :desc && small_nulls?)
|
336
|
+
end
|
337
|
+
|
338
|
+
def small_nulls?
|
339
|
+
# PostgreSQL considers NULLs larger than any value,
|
340
|
+
# opposite for SQLite and MySQL.
|
341
|
+
db_config = @relation.klass.connection_pool.db_config
|
342
|
+
db_config.adapter !~ /postg/ # postgres and postgis
|
343
|
+
end
|
344
|
+
|
345
|
+
def nullable_column?(column)
|
346
|
+
@nullable_columns.include?(column)
|
347
|
+
end
|
224
348
|
end
|
225
349
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord_cursor_paginate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- fatkodima
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-03-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -41,13 +41,13 @@ files:
|
|
41
41
|
- lib/activerecord_cursor_paginate/page.rb
|
42
42
|
- lib/activerecord_cursor_paginate/paginator.rb
|
43
43
|
- lib/activerecord_cursor_paginate/version.rb
|
44
|
-
homepage: https://github.com/
|
44
|
+
homepage: https://github.com/healthie/activerecord_cursor_paginate
|
45
45
|
licenses:
|
46
46
|
- MIT
|
47
47
|
metadata:
|
48
|
-
homepage_uri: https://github.com/
|
49
|
-
source_code_uri: https://github.com/
|
50
|
-
changelog_uri: https://github.com/
|
48
|
+
homepage_uri: https://github.com/healthie/activerecord_cursor_paginate
|
49
|
+
source_code_uri: https://github.com/healthie/activerecord_cursor_paginate
|
50
|
+
changelog_uri: https://github.com/healthie/activerecord_cursor_paginate/blob/master/CHANGELOG.md
|
51
51
|
post_install_message:
|
52
52
|
rdoc_options: []
|
53
53
|
require_paths:
|