graphql-connections 1.2.0 → 1.3.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/README.md +3 -1
- data/lib/graphql/connections/primary_key/asc.rb +30 -0
- data/lib/graphql/connections/primary_key/base.rb +107 -0
- data/lib/graphql/connections/primary_key/desc.rb +30 -0
- data/lib/graphql/connections/stable.rb +2 -2
- data/lib/graphql/connections/version.rb +1 -1
- data/lib/graphql/connections.rb +4 -1
- metadata +5 -3
- data/lib/graphql/connections/key_asc.rb +0 -69
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ed09e36d3d30a8e2cd939a1b9b39341168478d547e4b0e990798e612f6f83e49
|
4
|
+
data.tar.gz: bc35f6d38dcebf5a97ce0cf69d6540db2712046bddc15f5c1bca0c685115eac4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2408beb9fb3346e5ce7e980b462dc34762d5507bb65eb9c1051672d1dc0b8d33c2807d5113b0837a704ad3311bcbc27baeddb5bd4bb1177e8e748d00ca0f2b98
|
7
|
+
data.tar.gz: 042f6ee93e8fbc8391122ac5546bf18c3be595b2c45504daeff6dbec16240278141ad3e9a5d145e30a14c84e70d37ef03fb242e282c110f41ffd2605ebca81c4
|
data/README.md
CHANGED
@@ -59,7 +59,9 @@ Also, you can pass the `:desc` option to reverse the relation:
|
|
59
59
|
GraphQL::Connections::Stable.new(Message.all, keys: %w[name id], desc: true)
|
60
60
|
```
|
61
61
|
|
62
|
-
|
62
|
+
```ruby
|
63
|
+
GraphQL::Connections::Stable.new(Message.all, primary_key: :created_at, desc: true)
|
64
|
+
```
|
63
65
|
|
64
66
|
Also, you can disable opaque cursors by setting `opaque_cursor` param:
|
65
67
|
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Connections
|
5
|
+
# Implements pagination by one field with asc order
|
6
|
+
module PrimaryKey
|
7
|
+
class Asc < Base
|
8
|
+
PAGE_COMPARABLE_METHODS = {
|
9
|
+
previous: {query: :lt, cursor: :lteq},
|
10
|
+
next: {query: :gt, cursor: :gteq}
|
11
|
+
}
|
12
|
+
|
13
|
+
SLICED_COMPARABLE_METHODS = {
|
14
|
+
after: :gt,
|
15
|
+
before: :lt
|
16
|
+
}.freeze
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def first_limited_sorted_table
|
21
|
+
arel_table[primary_key].asc
|
22
|
+
end
|
23
|
+
|
24
|
+
def last_limited_sorted_table
|
25
|
+
arel_table[primary_key].desc
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Connections
|
5
|
+
module PrimaryKey
|
6
|
+
# Base class for PrimaryKey pagination implementations
|
7
|
+
class Base < ::GraphQL::Connections::Base
|
8
|
+
COMPARABLE_METHODS = %i[
|
9
|
+
gt lt lteq gteq
|
10
|
+
].freeze
|
11
|
+
|
12
|
+
def initialize(*args, primary_key: nil, **kwargs)
|
13
|
+
@primary_key = primary_key
|
14
|
+
|
15
|
+
super(*args, **kwargs)
|
16
|
+
end
|
17
|
+
|
18
|
+
def has_previous_page
|
19
|
+
if last
|
20
|
+
nodes.any? && items_exist?(type: :query, search: nodes.first[primary_key], page_type: :previous)
|
21
|
+
elsif after
|
22
|
+
items_exist?(type: :cursor, search: after_cursor, page_type: :previous)
|
23
|
+
else
|
24
|
+
false
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def has_next_page
|
29
|
+
if first
|
30
|
+
items_exist?(type: :query, search: nodes.last[primary_key], page_type: :next)
|
31
|
+
elsif before
|
32
|
+
items_exist?(type: :cursor, search: before_cursor, page_type: :next)
|
33
|
+
else
|
34
|
+
false
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def cursor_for(item)
|
39
|
+
cursor = serialize(item[primary_key])
|
40
|
+
cursor = encode(cursor) if opaque_cursor
|
41
|
+
cursor
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def page_comparable_method(query_type:, page_type:)
|
47
|
+
self.class::PAGE_COMPARABLE_METHODS.fetch(page_type).fetch(query_type)
|
48
|
+
end
|
49
|
+
|
50
|
+
def items_exist?(type:, search:, page_type:)
|
51
|
+
comparable_method = page_comparable_method(query_type: type, page_type: page_type)
|
52
|
+
|
53
|
+
if COMPARABLE_METHODS.exclude?(comparable_method)
|
54
|
+
raise ArgumentError.new("Unknown #{comparable_method} comparable type. Allowed #{COMPARABLE_METHODS.join(", ")}")
|
55
|
+
end
|
56
|
+
|
57
|
+
items.where(arel_table[primary_key].send(comparable_method, search)).exists?
|
58
|
+
end
|
59
|
+
|
60
|
+
def limited_relation
|
61
|
+
scope = sliced_relation
|
62
|
+
nodes = []
|
63
|
+
|
64
|
+
if first
|
65
|
+
nodes |=
|
66
|
+
scope
|
67
|
+
.reorder(first_limited_sorted_table)
|
68
|
+
.limit(first)
|
69
|
+
.to_a
|
70
|
+
end
|
71
|
+
|
72
|
+
if last
|
73
|
+
nodes |=
|
74
|
+
scope
|
75
|
+
.reorder(last_limited_sorted_table)
|
76
|
+
.limit(last)
|
77
|
+
.to_a.reverse!
|
78
|
+
end
|
79
|
+
|
80
|
+
nodes
|
81
|
+
end
|
82
|
+
|
83
|
+
def sliced_relation
|
84
|
+
items
|
85
|
+
.yield_self { |s| after ? sliced_items(items: s, cursor: after_cursor, type: :after) : s }
|
86
|
+
.yield_self { |s| before ? sliced_items(items: s, cursor: before_cursor, type: :before) : s }
|
87
|
+
end
|
88
|
+
|
89
|
+
def sliced_items(items:, cursor:, type:)
|
90
|
+
items.where(arel_table[primary_key].send(sliced_comparable_method(type), cursor))
|
91
|
+
end
|
92
|
+
|
93
|
+
def sliced_comparable_method(type)
|
94
|
+
self.class::SLICED_COMPARABLE_METHODS.fetch(type.to_sym)
|
95
|
+
end
|
96
|
+
|
97
|
+
def first_limited_sorted_table
|
98
|
+
raise NotImplementedError.new("method \"#{__method__}\" should be implemented in #{self.class.name} class")
|
99
|
+
end
|
100
|
+
|
101
|
+
def last_limited_sorted_table
|
102
|
+
raise NotImplementedError.new("method \"#{__method__}\" should be implemented in #{self.class.name} class")
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Connections
|
5
|
+
# Implements pagination by one field with desc order
|
6
|
+
module PrimaryKey
|
7
|
+
class Desc < Base
|
8
|
+
PAGE_COMPARABLE_METHODS = {
|
9
|
+
previous: {query: :gt, cursor: :gteq},
|
10
|
+
next: {query: :lt, cursor: :lteq}
|
11
|
+
}.freeze
|
12
|
+
|
13
|
+
SLICED_COMPARABLE_METHODS = {
|
14
|
+
after: :lt,
|
15
|
+
before: :gt
|
16
|
+
}.freeze
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def first_limited_sorted_table
|
21
|
+
arel_table[primary_key].desc
|
22
|
+
end
|
23
|
+
|
24
|
+
def last_limited_sorted_table
|
25
|
+
arel_table[primary_key].asc
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -14,9 +14,9 @@ module GraphQL
|
|
14
14
|
module Stable
|
15
15
|
def self.new(*args, desc: false, keys: nil, **kwargs)
|
16
16
|
if kwargs[:primary_key] || keys.nil?
|
17
|
-
|
17
|
+
cls = desc ? GraphQL::Connections::PrimaryKey::Desc : GraphQL::Connections::PrimaryKey::Asc
|
18
18
|
|
19
|
-
return
|
19
|
+
return cls.new(*args, **kwargs)
|
20
20
|
end
|
21
21
|
|
22
22
|
raise ArgumentError, "keyset for more that 2 keys is not implemented yet" if keys.length > 2
|
data/lib/graphql/connections.rb
CHANGED
@@ -11,10 +11,13 @@ end
|
|
11
11
|
require "graphql/connections/stable"
|
12
12
|
|
13
13
|
require "graphql/connections/base"
|
14
|
-
require "graphql/connections/key_asc"
|
15
14
|
|
16
15
|
require "graphql/connections/keyset/base"
|
17
16
|
require "graphql/connections/keyset/asc"
|
18
17
|
require "graphql/connections/keyset/desc"
|
19
18
|
|
19
|
+
require "graphql/connections/primary_key/base"
|
20
|
+
require "graphql/connections/primary_key/asc"
|
21
|
+
require "graphql/connections/primary_key/desc"
|
22
|
+
|
20
23
|
require "graphql/connections/chewy"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphql-connections
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Misha Merkushin
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-05-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -210,10 +210,12 @@ files:
|
|
210
210
|
- lib/graphql/connections.rb
|
211
211
|
- lib/graphql/connections/base.rb
|
212
212
|
- lib/graphql/connections/chewy.rb
|
213
|
-
- lib/graphql/connections/key_asc.rb
|
214
213
|
- lib/graphql/connections/keyset/asc.rb
|
215
214
|
- lib/graphql/connections/keyset/base.rb
|
216
215
|
- lib/graphql/connections/keyset/desc.rb
|
216
|
+
- lib/graphql/connections/primary_key/asc.rb
|
217
|
+
- lib/graphql/connections/primary_key/base.rb
|
218
|
+
- lib/graphql/connections/primary_key/desc.rb
|
217
219
|
- lib/graphql/connections/stable.rb
|
218
220
|
- lib/graphql/connections/version.rb
|
219
221
|
homepage: https://github.com/bibendi/graphql-connections
|
@@ -1,69 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module GraphQL
|
4
|
-
module Connections
|
5
|
-
# Implements pagination by one field with asc order
|
6
|
-
class KeyAsc < ::GraphQL::Connections::Base
|
7
|
-
def initialize(*args, primary_key: nil, **kwargs)
|
8
|
-
@primary_key = primary_key
|
9
|
-
|
10
|
-
super(*args, **kwargs)
|
11
|
-
end
|
12
|
-
|
13
|
-
def has_previous_page
|
14
|
-
if last
|
15
|
-
nodes.any? && items.where(arel_table[primary_key].lt(nodes.first[primary_key])).exists?
|
16
|
-
elsif after
|
17
|
-
items.where(arel_table[primary_key].lteq(after_cursor)).exists?
|
18
|
-
else
|
19
|
-
false
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def has_next_page
|
24
|
-
if first
|
25
|
-
nodes.any? && items.where(arel_table[primary_key].gt(nodes.last[primary_key])).exists?
|
26
|
-
elsif before
|
27
|
-
items.where(arel_table[primary_key].gteq(before_cursor)).exists?
|
28
|
-
else
|
29
|
-
false
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def cursor_for(item)
|
34
|
-
cursor = serialize(item[primary_key])
|
35
|
-
cursor = encode(cursor) if opaque_cursor
|
36
|
-
cursor
|
37
|
-
end
|
38
|
-
|
39
|
-
private
|
40
|
-
|
41
|
-
def limited_relation
|
42
|
-
scope = sliced_relation
|
43
|
-
nodes = []
|
44
|
-
|
45
|
-
if first
|
46
|
-
nodes |= scope
|
47
|
-
.reorder(arel_table[primary_key].asc)
|
48
|
-
.limit(first)
|
49
|
-
.to_a
|
50
|
-
end
|
51
|
-
|
52
|
-
if last
|
53
|
-
nodes |= scope
|
54
|
-
.reorder(arel_table[primary_key].desc)
|
55
|
-
.limit(last)
|
56
|
-
.to_a.reverse!
|
57
|
-
end
|
58
|
-
|
59
|
-
nodes
|
60
|
-
end
|
61
|
-
|
62
|
-
def sliced_relation
|
63
|
-
items
|
64
|
-
.yield_self { |s| after ? s.where(arel_table[primary_key].gt(after_cursor)) : s }
|
65
|
-
.yield_self { |s| before ? s.where(arel_table[primary_key].lt(before_cursor)) : s }
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|