rails_cursor_pagination 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/lib/rails_cursor_pagination/cursor.rb +2 -0
- data/lib/rails_cursor_pagination/paginator.rb +20 -2
- data/lib/rails_cursor_pagination/timestamp_cursor.rb +84 -0
- data/lib/rails_cursor_pagination/version.rb +1 -1
- data/lib/rails_cursor_pagination.rb +2 -0
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2410928079b14757601fdbb84b8c516a99070f5eee181ab464beeeeb00f302b6
|
4
|
+
data.tar.gz: 7f7e5a25d3977ad18964d35d0e2715978c57ccfdfe8624d229bd275deeb1b542
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 349ba3f27691109cc3e374dbc0c8340163b8af0b452f158e806f859b7b88e4f6ba7b88bb9a5b9a3c9080ccf53d00c100ba7e166f4b0aec2e2fa0c300591b7ff5
|
7
|
+
data.tar.gz: 802a9c37b80c59dc52c747d6727afa48650572448294114a1f5b70c6092a72d272beb51eeda50b13d2b009598396688eff4969e1d44f13bfa09f7a2f7097c490
|
data/CHANGELOG.md
CHANGED
@@ -14,6 +14,18 @@ These are the latest changes on the project's `master` branch that have not yet
|
|
14
14
|
Follow the same format as previous releases by categorizing your feature into "Added", "Changed", "Deprecated", "Removed", "Fixed", or "Security".
|
15
15
|
--->
|
16
16
|
|
17
|
+
## [0.4.0] - 2023-10-06
|
18
|
+
|
19
|
+
### Changed
|
20
|
+
- **Breaking change:** Raised minimum required Ruby version to 2.7
|
21
|
+
- **Breaking change:** Raised minimum required `activerecord` version to 6.0
|
22
|
+
|
23
|
+
### Added
|
24
|
+
- Test against Ruby version 3.2
|
25
|
+
|
26
|
+
### Fixed
|
27
|
+
- **Breaking change:** Ensure timestamp `order_by` fields (like `created_at`) will paginate results by honoring timestamp order down to microsecond resolution on comparison. This was done by changing the cursor logic for timestamp fields, which means that the cursors strings change from version 0.3.0 to 0.4.0 and old cursors cannot be decoded by the new gem version anymore.
|
28
|
+
|
17
29
|
## [0.3.0] - 2022-07-08
|
18
30
|
|
19
31
|
### Added
|
@@ -365,7 +365,7 @@ module RailsCursorPagination
|
|
365
365
|
# @param record [ActiveRecord] Model instance for which we want the cursor
|
366
366
|
# @return [String]
|
367
367
|
def cursor_for_record(record)
|
368
|
-
|
368
|
+
cursor_class.from_record(record: record, order_field: @order_field).encode
|
369
369
|
end
|
370
370
|
|
371
371
|
# Decode the provided cursor. Either just returns the cursor's ID or in case
|
@@ -375,7 +375,25 @@ module RailsCursorPagination
|
|
375
375
|
# @return [Integer, Array]
|
376
376
|
def decoded_cursor
|
377
377
|
memoize(:decoded_cursor) do
|
378
|
-
|
378
|
+
cursor_class.decode(encoded_string: @cursor, order_field: @order_field)
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
# Returns the appropriate class for the cursor based on the SQL type of the
|
383
|
+
# column used for ordering the relation.
|
384
|
+
#
|
385
|
+
# @return [Class<RailsCursorPagination::Cursor>]
|
386
|
+
def cursor_class
|
387
|
+
order_field_type = @relation
|
388
|
+
.column_for_attribute(@order_field)
|
389
|
+
.sql_type_metadata
|
390
|
+
.type
|
391
|
+
|
392
|
+
case order_field_type
|
393
|
+
when :datetime
|
394
|
+
TimestampCursor
|
395
|
+
else
|
396
|
+
Cursor
|
379
397
|
end
|
380
398
|
end
|
381
399
|
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RailsCursorPagination
|
4
|
+
# Cursor class that's used to uniquely identify a record and serialize and
|
5
|
+
# deserialize this cursor so that it can be used for pagination.
|
6
|
+
# This class expects the `order_field` of the record to be a timestamp and is
|
7
|
+
# to be used only when sorting a
|
8
|
+
class TimestampCursor < Cursor
|
9
|
+
class << self
|
10
|
+
# Decode the provided encoded cursor. Returns an instance of this
|
11
|
+
# `RailsCursorPagination::Cursor` class containing both the ID and the
|
12
|
+
# ordering field value. The ordering field is expected to be a timestamp
|
13
|
+
# and is always decoded in the UTC timezone.
|
14
|
+
#
|
15
|
+
# @param encoded_string [String]
|
16
|
+
# The encoded cursor
|
17
|
+
# @param order_field [Symbol]
|
18
|
+
# The column that is being ordered on. It needs to be a timestamp of a
|
19
|
+
# class that responds to `#strftime`.
|
20
|
+
# @raise [RailsCursorPagination::InvalidCursorError]
|
21
|
+
# In case the given `encoded_string` cannot be decoded properly
|
22
|
+
# @return [RailsCursorPagination::TimestampCursor]
|
23
|
+
# Instance of this class with a properly decoded timestamp cursor
|
24
|
+
def decode(encoded_string:, order_field:)
|
25
|
+
decoded = JSON.parse(Base64.strict_decode64(encoded_string))
|
26
|
+
|
27
|
+
new(
|
28
|
+
id: decoded[1],
|
29
|
+
order_field: order_field,
|
30
|
+
# Turn the order field value into a `Time` instance in UTC. A Rational
|
31
|
+
# number allows us to represent fractions of seconds, including the
|
32
|
+
# microseconds. In this way we can preserve the order of items with a
|
33
|
+
# microsecond precision.
|
34
|
+
# This also allows us to keep the size of the cursor small by using
|
35
|
+
# just a number instead of having to pass seconds and the fraction of
|
36
|
+
# seconds separately.
|
37
|
+
order_field_value: Time.at(decoded[0].to_r / (10**6)).utc
|
38
|
+
)
|
39
|
+
rescue ArgumentError, JSON::ParserError
|
40
|
+
raise InvalidCursorError,
|
41
|
+
"The given cursor `#{encoded_string}` " \
|
42
|
+
'could not be decoded to a timestamp'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Initializes the record. Overrides `Cursor`'s initializer making all params
|
47
|
+
# mandatory.
|
48
|
+
#
|
49
|
+
# @param id [Integer]
|
50
|
+
# The ID of the cursor record
|
51
|
+
# @param order_field [Symbol]
|
52
|
+
# The column or virtual column for ordering
|
53
|
+
# @param order_field_value [Object]
|
54
|
+
# The value that the +order_field+ of the record contains
|
55
|
+
def initialize(id:, order_field:, order_field_value:)
|
56
|
+
super id: id,
|
57
|
+
order_field: order_field,
|
58
|
+
order_field_value: order_field_value
|
59
|
+
end
|
60
|
+
|
61
|
+
# Encodes the cursor as an array containing the timestamp as microseconds
|
62
|
+
# from UNIX epoch and the id of the object
|
63
|
+
#
|
64
|
+
# @raise [RailsCursorPagination::ParameterError]
|
65
|
+
# The order field value needs to respond to `#strftime` to use the
|
66
|
+
# `TimestampCursor` class. Otherwise, a `ParameterError` is raised.
|
67
|
+
# @return [String]
|
68
|
+
def encode
|
69
|
+
unless @order_field_value.respond_to?(:strftime)
|
70
|
+
raise ParameterError,
|
71
|
+
"Could not encode #{@order_field} " \
|
72
|
+
"with value #{@order_field_value}." \
|
73
|
+
'It does not respond to #strftime. Is it a timestamp?'
|
74
|
+
end
|
75
|
+
|
76
|
+
Base64.strict_encode64(
|
77
|
+
[
|
78
|
+
@order_field_value.strftime('%s%6N').to_i,
|
79
|
+
@id
|
80
|
+
].to_json
|
81
|
+
)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -164,6 +164,8 @@ module RailsCursorPagination
|
|
164
164
|
|
165
165
|
require_relative 'rails_cursor_pagination/cursor'
|
166
166
|
|
167
|
+
require_relative 'rails_cursor_pagination/timestamp_cursor'
|
168
|
+
|
167
169
|
class << self
|
168
170
|
# Allows to configure this gem. Currently supported configuration values
|
169
171
|
# are:
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails_cursor_pagination
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nicolas Fricke
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-10-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '6.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '6.0'
|
27
27
|
description: This library is an implementation of cursor pagination for ActiveRecord
|
28
28
|
relations. Where a regular limit & offset pagination has issues with items that
|
29
29
|
are being deleted from or added to the collection on previous pages, cursor pagination
|
@@ -42,6 +42,7 @@ files:
|
|
42
42
|
- lib/rails_cursor_pagination/configuration.rb
|
43
43
|
- lib/rails_cursor_pagination/cursor.rb
|
44
44
|
- lib/rails_cursor_pagination/paginator.rb
|
45
|
+
- lib/rails_cursor_pagination/timestamp_cursor.rb
|
45
46
|
- lib/rails_cursor_pagination/version.rb
|
46
47
|
homepage: https://github.com/xing/rails_cursor_pagination
|
47
48
|
licenses:
|
@@ -59,14 +60,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
59
60
|
requirements:
|
60
61
|
- - ">="
|
61
62
|
- !ruby/object:Gem::Version
|
62
|
-
version: 2.
|
63
|
+
version: 2.7.0
|
63
64
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
65
|
requirements:
|
65
66
|
- - ">="
|
66
67
|
- !ruby/object:Gem::Version
|
67
68
|
version: '0'
|
68
69
|
requirements: []
|
69
|
-
rubygems_version: 3.
|
70
|
+
rubygems_version: 3.2.33
|
70
71
|
signing_key:
|
71
72
|
specification_version: 4
|
72
73
|
summary: Add cursor pagination to your ActiveRecord backed application.
|