graphql_preloader 1.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 +17 -0
- data/.bundle/config +2 -0
- data/.gitignore +1 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +33 -0
- data/README.md +93 -0
- data/lib/graphql_preloader.rb +1 -0
- data/lib/preload_function.rb +44 -0
- data/rgraphql_preload_ar.gemspec +10 -0
- metadata +65 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
!binary "U0hBMjU2":
|
|
3
|
+
metadata.gz: !binary |-
|
|
4
|
+
ZjhkMTBhYWMxM2FhNWE5YTA3ZDk3MDQxNjg4OTZlOWY3YTVjNjM2NTZlYmI3
|
|
5
|
+
MWMxOTdkN2RkZjQyODg5ZmQ1Yw==
|
|
6
|
+
data.tar.gz: !binary |-
|
|
7
|
+
YWRhOWNmNzg0Y2JiNWM0YzU3ZGI1ZGQxNDM5MWU2NzU3OWUyNTU5NjZhYWFj
|
|
8
|
+
NjQ2NGUxMzA1MTJhMzE2NjcxZQ==
|
|
9
|
+
SHA512:
|
|
10
|
+
metadata.gz: !binary |-
|
|
11
|
+
ODgyZWIwMTJkNGY5NDFkMWRlNjdjMzlmY2RjNmU4ZjA2NTgxMGE5MTMwOGFj
|
|
12
|
+
ZGM4Y2FjNWQ0MTM0NWE4MWFjYTg1Y2YzNGUwYzI0MTZlYTM2MjllYjA4OWEx
|
|
13
|
+
YTNmMzlhN2QzYTc0ZGZjMmZiZjQ0YjY5YjA5M2QyZTk2MDE3MGQ=
|
|
14
|
+
data.tar.gz: !binary |-
|
|
15
|
+
OGRlYTRhZjRlNjc2ZjRmNjQxOGI5MGM4ZmYzZTQwMjk0MjYyNTdmZjAwYmRk
|
|
16
|
+
ZGZlYmI2YWVkZWU2NDc0NDU3NTRlZTZlZDY1MGJkMGJkNDU3MTM2MGVhNjE2
|
|
17
|
+
YzM1YzY5OTE4NjRmY2QyNmQ3MzIyZTdiMjg2MDEzOGJlOGRlMzI=
|
data/.bundle/config
ADDED
data/.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*.gem
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
GEM
|
|
2
|
+
remote: https://gems.ruby-china.com/
|
|
3
|
+
specs:
|
|
4
|
+
activemodel (5.2.3)
|
|
5
|
+
activesupport (= 5.2.3)
|
|
6
|
+
activerecord (5.2.3)
|
|
7
|
+
activemodel (= 5.2.3)
|
|
8
|
+
activesupport (= 5.2.3)
|
|
9
|
+
arel (>= 9.0)
|
|
10
|
+
activesupport (5.2.3)
|
|
11
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
12
|
+
i18n (>= 0.7, < 2)
|
|
13
|
+
minitest (~> 5.1)
|
|
14
|
+
tzinfo (~> 1.1)
|
|
15
|
+
arel (9.0.0)
|
|
16
|
+
concurrent-ruby (1.1.5)
|
|
17
|
+
graphql (1.9.4)
|
|
18
|
+
i18n (1.6.0)
|
|
19
|
+
concurrent-ruby (~> 1.0)
|
|
20
|
+
minitest (5.11.3)
|
|
21
|
+
thread_safe (0.3.6)
|
|
22
|
+
tzinfo (1.2.5)
|
|
23
|
+
thread_safe (~> 0.1)
|
|
24
|
+
|
|
25
|
+
PLATFORMS
|
|
26
|
+
ruby
|
|
27
|
+
|
|
28
|
+
DEPENDENCIES
|
|
29
|
+
activerecord (~> 5.2.1)
|
|
30
|
+
graphql (>= 1.8.11)
|
|
31
|
+
|
|
32
|
+
BUNDLED WITH
|
|
33
|
+
2.0.1
|
data/README.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
## What's this gem do
|
|
2
|
+
|
|
3
|
+
preload ActiveRecord Associations when using graphql and ActiveRecord
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
`gem 'graphql_preloader'`
|
|
8
|
+
|
|
9
|
+
## Scene
|
|
10
|
+
|
|
11
|
+
Your original code of resolver might look like this:
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
class Resolvers::ProfileResolver < GraphQL::Function
|
|
15
|
+
description 'User profile'
|
|
16
|
+
|
|
17
|
+
type Types::ProfileType
|
|
18
|
+
|
|
19
|
+
def _call(_, args, ctx)
|
|
20
|
+
ctx[:current_user]
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
If the query like this:
|
|
26
|
+
```
|
|
27
|
+
query{
|
|
28
|
+
profile{
|
|
29
|
+
id
|
|
30
|
+
works{
|
|
31
|
+
comments{
|
|
32
|
+
replyUser{
|
|
33
|
+
name
|
|
34
|
+
}
|
|
35
|
+
content
|
|
36
|
+
}
|
|
37
|
+
name
|
|
38
|
+
id
|
|
39
|
+
likes{
|
|
40
|
+
owner{
|
|
41
|
+
name
|
|
42
|
+
works{
|
|
43
|
+
name
|
|
44
|
+
likes{
|
|
45
|
+
owner{
|
|
46
|
+
name
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
name
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
It will cause Multi-level nested N + 1 problem.
|
|
59
|
+
|
|
60
|
+
And you want to resolve it, you can write like this:
|
|
61
|
+
|
|
62
|
+
```ruby
|
|
63
|
+
class Resolvers::ProfileResolver < GraphQL::Function
|
|
64
|
+
description 'User profile'
|
|
65
|
+
|
|
66
|
+
type Types::ProfileType
|
|
67
|
+
|
|
68
|
+
def _call(_, args, ctx)
|
|
69
|
+
User.includes([works: [comments: :reply_user, likes: [owner: [works: [likes: :owner]]]]]).find(ctx[:current_user].id)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
You will manually resolve N + 1 problem in every resolver.Worse, even if only one field is used, you need to request all the tables included.
|
|
75
|
+
|
|
76
|
+
## Usage
|
|
77
|
+
|
|
78
|
+
Your Resolver inherits from `PreloadFunction` instead of `GraphQL::Function`.
|
|
79
|
+
Defining `_call` method instead of `call`
|
|
80
|
+
Using `included_model(your_model_name)` instead of your original includes statement.
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
```ruby
|
|
84
|
+
class Resolvers::ProfileResolver < PreloadFunction
|
|
85
|
+
description 'User profile'
|
|
86
|
+
|
|
87
|
+
type Types::ProfileType
|
|
88
|
+
|
|
89
|
+
def _call(_, args, ctx)
|
|
90
|
+
included_model(User).find(ctx[:current_user].id)
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require 'preload_function'
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
require 'graphql'
|
|
2
|
+
class PreloadFunction < GraphQL::Function
|
|
3
|
+
def call obj, args, ctx
|
|
4
|
+
@ctx = ctx
|
|
5
|
+
@json_tree = {}
|
|
6
|
+
@result_tree = {}
|
|
7
|
+
_call obj, args, ctx
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def included_model model_class
|
|
11
|
+
@root_model_class = model_class
|
|
12
|
+
recursion query_tree
|
|
13
|
+
gen_accociations_tree model_class
|
|
14
|
+
model_class.includes @result_tree
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def query_tree
|
|
18
|
+
@ctx.query.document.children.first.selections.first
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def recursion node, tree = @json_tree
|
|
22
|
+
node_key = node.name.underscore.to_sym
|
|
23
|
+
tree[node_key] = {}
|
|
24
|
+
node.selections.each do |n|
|
|
25
|
+
recursion n, tree[node_key]
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def json_tree_without_root
|
|
30
|
+
@json_tree.values.first
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def gen_accociations_tree model_class = @root_model_class, tree = json_tree_without_root, result_tree = @result_tree
|
|
34
|
+
tree.each do |k, v|
|
|
35
|
+
if v.present? && model_class.reflect_on_all_associations.map(&:name).include?(k)
|
|
36
|
+
result_tree[k.to_sym] = {}
|
|
37
|
+
next if model_class.reflections[k.to_s].options[:polymorphic]
|
|
38
|
+
_model_class = model_class.reflections[k.to_s].class_name.constantize
|
|
39
|
+
gen_accociations_tree _model_class, tree[k], result_tree[k.to_sym]
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
Gem::Specification.new do |s|
|
|
2
|
+
s.name = 'graphql_preloader'
|
|
3
|
+
s.version = "1.1.0"
|
|
4
|
+
s.date = Time.now.strftime("%Y-%m-%d")
|
|
5
|
+
s.summary = %q{rails graphql preload ar association in resolver}
|
|
6
|
+
s.files = `git ls-files`.split($/)
|
|
7
|
+
s.authors = ["tinyfeng.hou"]
|
|
8
|
+
s.license = 'MIT'
|
|
9
|
+
s.add_dependency "graphql", ">=1.8.11"
|
|
10
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: graphql_preloader
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- tinyfeng.hou
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2019-04-21 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: graphql
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ! '>='
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: 1.8.11
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ! '>='
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: 1.8.11
|
|
27
|
+
description:
|
|
28
|
+
email:
|
|
29
|
+
executables: []
|
|
30
|
+
extensions: []
|
|
31
|
+
extra_rdoc_files: []
|
|
32
|
+
files:
|
|
33
|
+
- .bundle/config
|
|
34
|
+
- .gitignore
|
|
35
|
+
- Gemfile
|
|
36
|
+
- Gemfile.lock
|
|
37
|
+
- README.md
|
|
38
|
+
- lib/graphql_preloader.rb
|
|
39
|
+
- lib/preload_function.rb
|
|
40
|
+
- rgraphql_preload_ar.gemspec
|
|
41
|
+
homepage:
|
|
42
|
+
licenses:
|
|
43
|
+
- MIT
|
|
44
|
+
metadata: {}
|
|
45
|
+
post_install_message:
|
|
46
|
+
rdoc_options: []
|
|
47
|
+
require_paths:
|
|
48
|
+
- lib
|
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ! '>='
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '0'
|
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
55
|
+
requirements:
|
|
56
|
+
- - ! '>='
|
|
57
|
+
- !ruby/object:Gem::Version
|
|
58
|
+
version: '0'
|
|
59
|
+
requirements: []
|
|
60
|
+
rubyforge_project:
|
|
61
|
+
rubygems_version: 2.7.9
|
|
62
|
+
signing_key:
|
|
63
|
+
specification_version: 4
|
|
64
|
+
summary: rails graphql preload ar association in resolver
|
|
65
|
+
test_files: []
|