graphql_lazy_load 0.1.0 → 0.2.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/Gemfile.lock +2 -2
- data/README.md +91 -5
- data/gems/graphql_lazy_load-0.1.0.gem +0 -0
- data/lib/graphql_lazy_load/version.rb +1 -1
- data/lib/graphql_lazy_load.rb +68 -3
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 724af5e1b3fe1f2fbff97284fe54f2b20d9ddd9e3dddd3932c2f5b913c678873
|
4
|
+
data.tar.gz: adfcdb624948134a38390d7470898d8d038982dd917d76dda82eb898f3ffaadd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 81e56ea916ed8ae3173bd6629b037960f56f0edcb5031b64d7ad12a6c38ea1a293d98bca839955311adee539f300b1a4a7ab20a8a07ea3cc7394aaa0e2005705
|
7
|
+
data.tar.gz: 6062acf99ebc505293eb69bd5d917048f89927aa5be346cb8d86440fd70c05dbe370b193c007f1d00f3c6ef1a78d393a63955c3d393402432074316c2c776310
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
graphql_lazy_load (0.
|
4
|
+
graphql_lazy_load (0.2.0)
|
5
5
|
activerecord (>= 4.1.16)
|
6
6
|
graphql (>= 1.3.0)
|
7
7
|
|
@@ -38,7 +38,7 @@ GEM
|
|
38
38
|
concurrent-ruby (1.1.5)
|
39
39
|
crass (1.0.4)
|
40
40
|
erubi (1.8.0)
|
41
|
-
graphql (1.9.
|
41
|
+
graphql (1.9.12)
|
42
42
|
i18n (1.6.0)
|
43
43
|
concurrent-ruby (~> 1.0)
|
44
44
|
jaro_winkler (1.5.3)
|
data/README.md
CHANGED
@@ -6,7 +6,7 @@ Lazy executor for activerecord associations and graphql gem.
|
|
6
6
|
|
7
7
|
GraphqlLazyLoad requires ActiveRecord >= 4.1.16 and Graphql >= 1.3.0. To use add this line to your application's Gemfile:
|
8
8
|
```ruby
|
9
|
-
gem 'graphql_lazy_load'
|
9
|
+
gem 'graphql_lazy_load', '~> 0.2.0'
|
10
10
|
```
|
11
11
|
Then run `bundle install`.
|
12
12
|
|
@@ -15,6 +15,7 @@ Or install it yourself as:
|
|
15
15
|
$ gem install graphql_lazy_load
|
16
16
|
|
17
17
|
## Usage
|
18
|
+
### ActiveRecordRelation
|
18
19
|
To use, first add the executor (`GraphqlLazyLoad::ActiveRecordRelation`) to graphqls schema:
|
19
20
|
```ruby
|
20
21
|
class MySchema < GraphQL::Schema
|
@@ -32,11 +33,37 @@ def field_name
|
|
32
33
|
GraphqlLazyLoad::ActiveRecordRelation.new(self, :association_name)
|
33
34
|
end
|
34
35
|
```
|
36
|
+
### Custom
|
37
|
+
If you want to lazy load a non active record association you can use the `Custom` loader, first add the executor (`GraphqlLazyLoad::Custom`) to graphqls schema (both can be in the schema together):
|
38
|
+
```ruby
|
39
|
+
class MySchema < GraphQL::Schema
|
40
|
+
mutation(Types::MutationType)
|
41
|
+
query(Types::QueryType)
|
42
|
+
|
43
|
+
lazy_resolve(GraphqlLazyLoad::Custom, :result)
|
44
|
+
end
|
45
|
+
```
|
46
|
+
|
47
|
+
Now you can start using it! Wherever you have a something to lazy load, the syntax is:
|
48
|
+
```ruby
|
49
|
+
field :field_name, Types::AssociationType, null: false
|
50
|
+
def field_name
|
51
|
+
GraphqlLazyLoad::Custom.new(self, :association_name, object.id) do |ids|
|
52
|
+
# return a hash with key matching object.id
|
53
|
+
AssociationName.where(id: ids).reduce({}) do |acc, value|
|
54
|
+
acc[value.id] = value
|
55
|
+
acc
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
```
|
60
|
+
Values passed to the `Custom` initializer are `self`, `unique_identifier`, `unique_id` (gets passed to block, and is used to retrieve the values), you can also pass an optional value `params` (gets passed as second argument to block). It is important to note that data is grouped by `unique_identifier` and `params`.
|
35
61
|
## Examples
|
36
|
-
If you have two models `Team` which can have many `
|
62
|
+
If you have two models `Team` which can have many `Player`s. To lazy load players from teams do the following:
|
63
|
+
### ActiveRecordRelation
|
37
64
|
```ruby
|
38
65
|
module Types
|
39
|
-
class
|
66
|
+
class TeamType < Types::BaseObject
|
40
67
|
...
|
41
68
|
field :players, [Types::PlayerType], null: false
|
42
69
|
def players
|
@@ -48,7 +75,7 @@ end
|
|
48
75
|
And to lazy load teams from players do the following:
|
49
76
|
```ruby
|
50
77
|
module Types
|
51
|
-
class
|
78
|
+
class PlayerType < Types::BaseObject
|
52
79
|
...
|
53
80
|
field :team, Types::TeamType, null: false
|
54
81
|
def team
|
@@ -57,8 +84,46 @@ module Types
|
|
57
84
|
end
|
58
85
|
end
|
59
86
|
```
|
87
|
+
### Custom
|
88
|
+
```ruby
|
89
|
+
module Types
|
90
|
+
class TeamType < Types::BaseObject
|
91
|
+
...
|
92
|
+
field :players, [Types::PlayerType], null: false
|
93
|
+
def players
|
94
|
+
GraphqlLazyLoad::Custom.new(self, :players, object.id) do |team_ids|
|
95
|
+
# return a hash with key matching object.id
|
96
|
+
Player.where(team_id: team_ids).reduce({}) do |acc, player|
|
97
|
+
(acc[player.team_id] ||= []).push(player)
|
98
|
+
acc
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
```
|
105
|
+
And to lazy load teams from players do the following:
|
106
|
+
```ruby
|
107
|
+
module Types
|
108
|
+
class PlayerType < Types::BaseObject
|
109
|
+
...
|
110
|
+
field :team, Types::TeamType, null: false
|
111
|
+
def team
|
112
|
+
GraphqlLazyLoad::Custom.new(self, :team, object.team_id) do |team_ids|
|
113
|
+
# return a hash with key matching object.team_id
|
114
|
+
Team.where(id: team_ids).reduce({}) do |acc, team|
|
115
|
+
acc[team.id] = team
|
116
|
+
acc
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
```
|
123
|
+
|
60
124
|
### Scoping
|
61
|
-
The great thing
|
125
|
+
The great thing is you can pass scopes/params! So for the example above if you want to allow sorting (or query, paging, etc) do the following.
|
126
|
+
### ActiveRecordRelation
|
62
127
|
```ruby
|
63
128
|
module Types
|
64
129
|
class PlayerType < Types::BaseObject
|
@@ -75,6 +140,27 @@ module Types
|
|
75
140
|
end
|
76
141
|
```
|
77
142
|
|
143
|
+
### Custom
|
144
|
+
```ruby
|
145
|
+
module Types
|
146
|
+
class PlayerType < Types::BaseObject
|
147
|
+
...
|
148
|
+
field :players, [Types::PlayerType], null: false do
|
149
|
+
argument :order, String, required: false
|
150
|
+
end
|
151
|
+
def players(order: nil)
|
152
|
+
GraphqlLazyLoad::Custom.new(self, :players, object.id, {order: order}) do |team_ids, params|
|
153
|
+
query = Player.where(team_id: team_ids)
|
154
|
+
query = query.order(params[:order].underscore) if params[:order]
|
155
|
+
query.reduce({}) do |acc, player|
|
156
|
+
(acc[player.team_id] ||= []).push(player)
|
157
|
+
acc
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
```
|
78
164
|
To test this out try the example app at [graph_test](https://github.com/jonathongardner/graph_test)
|
79
165
|
|
80
166
|
## Contributing
|
Binary file
|
data/lib/graphql_lazy_load.rb
CHANGED
@@ -4,6 +4,72 @@ require "graphql_lazy_load/version"
|
|
4
4
|
require "active_record"
|
5
5
|
|
6
6
|
module GraphqlLazyLoad
|
7
|
+
class Custom
|
8
|
+
def initialize(type, unique_identifier, value, **params, &block)
|
9
|
+
@unique_identifier = unique_identifier
|
10
|
+
@params = params
|
11
|
+
@block = block
|
12
|
+
@value = value
|
13
|
+
# Initialize the loading state for this query,
|
14
|
+
# or get the previously-initiated state
|
15
|
+
# scope cant be used as a hash key because when .hash is called on diff
|
16
|
+
# for ~same~ scopes its diff every time but scope == scope will return true if ~same~
|
17
|
+
@lazy = type.context[context_key] ||= {
|
18
|
+
values_to_load: Set.new,
|
19
|
+
ids: Set.new,
|
20
|
+
results: {}
|
21
|
+
}
|
22
|
+
# Register this to be loaded later unless we've already queued or loaded it
|
23
|
+
return if already_loaded_or_queued?
|
24
|
+
lazy_values.add(value)
|
25
|
+
lazy_ids.add(value)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Return the loaded record, hitting the database if needed
|
29
|
+
def result
|
30
|
+
if !already_loaded? && any_to_load?
|
31
|
+
lazy_results.merge!(block_results)
|
32
|
+
lazy_values.clear
|
33
|
+
end
|
34
|
+
lazy_results[value]
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
attr_reader :unique_identifier, :params, :value
|
39
|
+
|
40
|
+
def block_results
|
41
|
+
@block.call(lazy_values, params)
|
42
|
+
end
|
43
|
+
|
44
|
+
def context_key
|
45
|
+
[unique_identifier, params]
|
46
|
+
end
|
47
|
+
|
48
|
+
def already_loaded_or_queued?
|
49
|
+
lazy_ids.include?(object_id)
|
50
|
+
end
|
51
|
+
|
52
|
+
def already_loaded?
|
53
|
+
lazy_results.key?(object_id)
|
54
|
+
end
|
55
|
+
|
56
|
+
def any_to_load?
|
57
|
+
lazy_values.any?
|
58
|
+
end
|
59
|
+
|
60
|
+
def lazy_ids
|
61
|
+
@lazy[:ids]
|
62
|
+
end
|
63
|
+
|
64
|
+
def lazy_values
|
65
|
+
@lazy[:values_to_load]
|
66
|
+
end
|
67
|
+
|
68
|
+
def lazy_results
|
69
|
+
@lazy[:results]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
7
73
|
class ActiveRecordRelation
|
8
74
|
def initialize(type, association, scope: nil)
|
9
75
|
@object_class = type.object.class
|
@@ -19,8 +85,7 @@ module GraphqlLazyLoad
|
|
19
85
|
@lazy = {
|
20
86
|
objects_to_load: Set.new,
|
21
87
|
ids: Set.new,
|
22
|
-
results: {}
|
23
|
-
scope: scope
|
88
|
+
results: {}
|
24
89
|
}
|
25
90
|
type.context[context_key].push(@lazy)
|
26
91
|
end
|
@@ -52,7 +117,7 @@ module GraphqlLazyLoad
|
|
52
117
|
end
|
53
118
|
|
54
119
|
def already_loaded_or_queued?
|
55
|
-
|
120
|
+
lazy_ids.include?(object_id)
|
56
121
|
end
|
57
122
|
|
58
123
|
def already_loaded?
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphql_lazy_load
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonathon Gardner
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-09-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -140,6 +140,7 @@ files:
|
|
140
140
|
- Rakefile
|
141
141
|
- bin/console
|
142
142
|
- bin/setup
|
143
|
+
- gems/graphql_lazy_load-0.1.0.gem
|
143
144
|
- graphql_lazy_load.gemspec
|
144
145
|
- lib/graphql_lazy_load.rb
|
145
146
|
- lib/graphql_lazy_load/version.rb
|