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.
@@ -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=
@@ -0,0 +1,2 @@
1
+ ---
2
+ BUNDLE_JOBS: "4"
@@ -0,0 +1 @@
1
+ *.gem
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://gems.ruby-china.com"
4
+
5
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
6
+ gemspec
7
+ gem 'graphql', '>= 1.8.11'
8
+
@@ -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
@@ -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: []