graphql_preload_queries 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 89226168aa382eb59c56754b96a4eaa64c51c5f06fc6fd8d831b7795d84adf0e
4
- data.tar.gz: b29ec85aa619a1f7412944d6f50388f68c9b196cc5e8607bc22fd163f3a64ed1
3
+ metadata.gz: fcc53358f8564b5b00d02cf7a341a7a82af9a9f02db2458fa4902f16d10847fb
4
+ data.tar.gz: 959b2a80b05637e60127762fae8fc765fff6c28c5438099cefbbe40c2c37a8c6
5
5
  SHA512:
6
- metadata.gz: 42df9aacf5b59d341fc5498a61890a1ecd5c76713179c94b81696084af7d9d4f52abdd105c26a04775aa6b8199f86398841bf230127df711ffceef386752f7f9
7
- data.tar.gz: cded97146bc935064f7dcaa94034deffd06adf1b6cf3c2daaacf746fb11eef542b261debd505ccb8963ec3b67f60cf7386d4829aeaa13feaed024786fa7ec04e
6
+ metadata.gz: 12797d60fbcdb9d528a56563d29b22c14555de16f4d0e34d063efc48444ec9e0936e854f5cf4912b7575720b40f7f79bfee25ab0b13039f9276efad5b99591e1
7
+ data.tar.gz: 991bb3d2cf4c6a8ccc2df2ce26f48cf564d6a37c6bc5f4a68a0d8de8a6d8ae8c48b62a4595b800dd62f72dcca180a31f23e3c28d0025625e76dea6c1f758961d
@@ -45,4 +45,5 @@ jobs:
45
45
  run: |
46
46
  bundle exec rspec
47
47
  - name: Code style (Rubocop)
48
- run: bundle exec rubocop
48
+ run: bundle exec rubocop
49
+ if: matrix.ruby == '2.5'
data/.rubocop.yml CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  require: rubocop-rspec
4
4
  AllCops:
5
- TargetRubyVersion: 2.4
5
+ TargetRubyVersion: 2.5
6
6
 
7
7
  RSpec/FilePath:
8
8
  Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 0.4.0 (30-05-2021)
2
+ - feat: refactor `include_gql_preloads` to auto calculate `query_key` and make it optional
3
+ - feat: support `:preload` option when defining a field
4
+
1
5
  ## 0.3.1 (22-01-2021)
2
6
  - feat: auto camelize key for queries and mutations
3
7
 
data/Gemfile CHANGED
@@ -8,6 +8,7 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
8
8
  # Bundler will treat runtime dependencies like base dependencies, and
9
9
  # development dependencies will be added by default to the :development group.
10
10
  gemspec
11
+ gem 'byebug'
11
12
 
12
13
  # Declare any dependencies that are still in development here instead of in
13
14
  # your gemspec. These might include edge Rails or gems from your path or
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- graphql_preload_queries (0.3.1)
4
+ graphql_preload_queries (0.4.0)
5
5
  graphql
6
6
  rails
7
7
 
@@ -65,6 +65,7 @@ GEM
65
65
  zeitwerk (~> 2.2, >= 2.2.2)
66
66
  ast (2.4.1)
67
67
  builder (3.2.4)
68
+ byebug (11.1.3)
68
69
  concurrent-ruby (1.1.7)
69
70
  crass (1.0.6)
70
71
  database_cleaner (1.8.5)
@@ -86,11 +87,13 @@ GEM
86
87
  marcel (0.3.3)
87
88
  mimemagic (~> 0.3.2)
88
89
  method_source (1.0.0)
89
- mimemagic (0.3.5)
90
- mini_mime (1.0.2)
90
+ mimemagic (0.3.10)
91
+ nokogiri (~> 1)
92
+ rake
93
+ mini_mime (1.1.0)
91
94
  mini_portile2 (2.4.0)
92
95
  minitest (5.14.2)
93
- nio4r (2.5.4)
96
+ nio4r (2.5.7)
94
97
  nokogiri (1.10.10)
95
98
  mini_portile2 (~> 2.4.0)
96
99
  parallel (1.20.1)
@@ -183,6 +186,7 @@ PLATFORMS
183
186
  ruby
184
187
 
185
188
  DEPENDENCIES
189
+ byebug
186
190
  database_cleaner-active_record
187
191
  graphql_preload_queries!
188
192
  rspec-rails
data/README.md CHANGED
@@ -1,57 +1,51 @@
1
1
  # GraphqlPreloadQueries
2
- This gem helps you to define all nested preloads to be added when required for graphql data results and avoid the common problem "N+1 Queries".
2
+ This gem permits your graphql application to define association preloads to improve app performance by removing N+1 query issues.
3
3
 
4
4
  ## Usage
5
5
  * Object Type
6
6
  ```ruby
7
7
  class UserType < Types::BaseObject
8
- add_preload 'parents|allParents', { preload: :parents, friends: :friends, parents: :parents }
9
- add_preload :friends, { parents: { preload: :parents, parents: :parents, friends: :friends } }
10
-
11
8
  field :id, Int, null: true
12
9
  field :name, String, null: true
13
- field :friends, [Types::UserType], null: false
14
- field :parents, [Types::UserType], null: false
10
+ field :parents, [Types::UserType], null: false, preload: true
11
+ field :friends, [Types::UserType], null: false, preload: :user_friends
15
12
  end
16
13
  ```
17
- Examples:
18
- * ```add_preload(:friends)```
19
- ```:friends``` association will be preloaded if query includes ```friends```, like: ```user(id: 10) { friends { ... } }```
20
-
21
- * ```add_preload(:allFriends, :friends)```
22
- ```:friends``` association will be preloaded if query includes ```allFriends```, like: ```user(id: 10) { allFriends { ... } }```
23
-
24
- * ```add_preload(:allFriends, { preload: :friends, parents: :parents })```
25
- ```:preload``` key can be used to indicate the association name when defining nested preloads, like: ```user(id: 10) { allFriends { id parents { ... } } }```
26
14
 
27
- * ```add_preload(:friends, { allParents: :parents })```
28
- (Nested 1 lvl preloading) ```friends: :parents``` association will be preloaded if query includes ```allParents```, like: ```user(id: 10) { friends { allParents { ... } } }```
29
-
30
- * ```add_preload(:friends, { allParents: { preload: :parents, friends: :friends } })```
31
- (Nested 2 levels preloading) ```friends: { parents: :friends }``` association will be preloaded if query includes ```friends``` inside ```parents```, like: ```user(id: 10) { friends { allParents { { friends { ... } } } } }```
32
-
33
- * ```add_preload('friends|allFriends', :friends)```
34
- (Multiple gql queries) ```:friends``` association will be preloaded if query includes ```friends``` or ```allFriends```, like: ```user(id: 10) { friends { ... } }``` OR ```user(id: 10) { allFriends { ... } }```
35
-
36
- * ```add_preload('ignoredFriends', 'ignored_friends.user')```
37
- (Deep preloading) ```{ ignored_friends: :user }``` association will be preloaded if query includes ```inogredFriends```, like: ```user(id: 10) { ignoredFriends { ... } }```
15
+ `preload:` accepts:
16
+ - `true`: Will use field key as the association name
17
+ `field :parents, ..., preload: true` will preload `parents` association
18
+ - `Symbol`: Custom association name
19
+ `field :friends, ..., preload: :user_friends` will preload `user_friends` association
20
+ - `String`: Tied associations
21
+ `field :excluded_friends, ..., preload: 'excluded_friends.user'` will preload `excluded_friends -> user` association
22
+ - `Hash`: Deep preload definitions
23
+ `field :best_friends, ..., preload: { preload: :user_friends, parents: :parents }'`
24
+ * Will preload `user_friends` and `user_friends.parents` only if query includes inner definition, like `user(id: 10) { bestFriends { id parents { ... } } }`
25
+ * Will not preload `user_friends.parents` if query does not include inner definition, like `user(id: 10) { bestFriends { id } }`
26
+
38
27
 
39
28
  * Preloads in query results
40
- ```ruby
41
- # queries/users.rb
42
- def user(id:)
43
- # includes all preloads defined in user type
44
- # Sample: user(id: 10){ friends { id } }
45
- # :friends will be preloaded inside "user" sql query
46
- user = include_gql_preloads(:user, User.where(id: id))
47
-
48
- # does not include user type preloads (only sub query preloads will be applied)
49
- # Sample: user(id: 10){ friends { id parents { ... } } }
50
- # Only :parents will be preloaded inside "friends" sql query
51
- user = User.find(id)
52
- end
53
- ```
54
- - include_gql_preloads: Will preload all preloads configured in UserType based on the gql query.
29
+ - BEFORE
30
+ ```ruby
31
+ # queries/users.rb
32
+ def users(ids:)
33
+ users = User.where(id: ids)
34
+ end
35
+ ```
36
+ Does not apply preloads to the root query.
37
+ - AFTER
38
+ ```ruby
39
+ def users(ids:)
40
+ user = include_gql_preloads(User.where(id: id))
41
+ end
42
+ ```
43
+ Root query applies all defined preloads
44
+
45
+ - `include_gql_preloads(collection, query_key: nil, type_klass: nil)`: Will include all preloads configured in `type_klass` (UserType) based on the gql query.
46
+ - `collection` (ActiveRecordCollection) Query results
47
+ - `query_key` (String | Sym, default: method name) Field result key
48
+ - `type_klass:` (GQL TypeClass, default: calculates using query_key)
55
49
 
56
50
  * Preloads in mutation results
57
51
  ```ruby
@@ -60,12 +54,14 @@ This gem helps you to define all nested preloads to be added when required for g
60
54
  field :users, [Types::UserType], null: true
61
55
  def resolve(ids:)
62
56
  affected_users = User.where(id: ids)
63
- affected_users = include_gql_preloads(:users, affected_users)
64
- puts affected_users.first&.friends # will print preloaded friends data
57
+ affected_users = include_gql_preloads(affected_users, query_key: :users)
65
58
  { users: affected_users }
66
59
  end
67
60
  ```
68
- - include_gql_preloads: Will preload all preloads configured in UserType based on the gql query.
61
+ - `include_gql_preloads(collection, query_key: , type_klass: nil)`: Will include all preloads configured in `type_klass` (UserType) based on the gql query.
62
+ - `collection` (ActiveRecordCollection) Query results
63
+ - `query_key` (String | Sym) Field result key
64
+ - `type_klass:` (GQL TypeClass, default: calculates using query_key)
69
65
 
70
66
  ## Installation
71
67
  Add this line to your application's Gemfile:
@@ -5,11 +5,11 @@ Rails.application.config.to_prepare do
5
5
  GraphQL::Schema::Mutation.class_eval do
6
6
  # TODO: auto recover type_klass using result key
7
7
  # Add corresponding preloads to mutation results
8
- # @param gql_result_key (String | Sym)
8
+ # @param query_key (String | Sym)
9
9
  # @param collection (ActiveCollection)
10
10
  # @param type_klass (GQL TypeClass)
11
- def include_gql_preloads(gql_result_key, collection, type_klass = nil)
12
- gql_result_key = GraphQL::Schema::Member::BuildType.camelize(gql_result_key.to_s)
11
+ def include_gql_preloads(collection, query_key:, type_klass: nil)
12
+ gql_result_key = GraphQL::Schema::Member::BuildType.camelize(query_key.to_s)
13
13
  type_klass ||= preload_type_klass(gql_result_key.to_s)
14
14
  klass = GraphqlPreloadQueries::Extensions::Preload
15
15
  ast_node = preload_find_node(gql_result_key)
@@ -31,6 +31,14 @@ Rails.application.config.to_prepare do
31
31
  key = GraphQL::Schema::Member::BuildType.camelize(key.to_s)
32
32
  preloads[key] = preload
33
33
  end
34
+
35
+ alias_method :field_old, :field
36
+ def field(*args, **kwargs, &block)
37
+ preload = kwargs.delete(:preload)
38
+ key = args[0]
39
+ add_preload(key, preload == true ? key : preload) if preload
40
+ field_old(*args, **kwargs, &block)
41
+ end
34
42
  end
35
43
  end
36
44
  end
@@ -3,14 +3,14 @@
3
3
  # preload resolver for queries
4
4
  Rails.application.config.to_prepare do
5
5
  Types::QueryType.class_eval do
6
- # TODO: auto recover type_klass using result key
7
6
  # Add corresponding preloads to query results
8
7
  # Note: key is automatically calculated based on method name
9
- # @param gql_result_key (String | Sym)
10
8
  # @param collection (ActiveCollection)
11
9
  # @param type_klass (GQL TypeClass, default: calculates using return type)
12
- def include_gql_preloads(gql_result_key, collection, type_klass = nil)
13
- gql_result_key = GraphQL::Schema::Member::BuildType.camelize(gql_result_key.to_s)
10
+ # @param query_key (String | Sym) Default method name
11
+ def include_gql_preloads(collection, query_key: nil, type_klass: nil)
12
+ query_key ||= caller_locations(1, 1)[0].label
13
+ gql_result_key = GraphQL::Schema::Member::BuildType.camelize(query_key.to_s)
14
14
  type_klass ||= preload_type_klass(gql_result_key.to_s)
15
15
  klass = GraphqlPreloadQueries::Extensions::Preload
16
16
  ast_node = preload_find_node(gql_result_key)
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
13
13
  spec.description = 'Permit to avoid N+1 queries problem when using graphql queries'
14
14
  spec.homepage = 'https://github.com/owen2345/graphql_preload_queries'
15
15
  spec.license = 'MIT'
16
- spec.required_ruby_version = Gem::Requirement.new('>= 2.4.0')
16
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.0') # rubocop:disable Gemspec/RequiredRubyVersion
17
17
 
18
18
  # spec.metadata["allowed_push_host"] = ""
19
19
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GraphqlPreloadQueries
4
- VERSION = '0.3.1'
4
+ VERSION = '0.4.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql_preload_queries
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - owen2345
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-01-22 00:00:00.000000000 Z
11
+ date: 2021-05-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: graphql
@@ -154,7 +154,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
154
154
  requirements:
155
155
  - - ">="
156
156
  - !ruby/object:Gem::Version
157
- version: 2.4.0
157
+ version: '2.0'
158
158
  required_rubygems_version: !ruby/object:Gem::Requirement
159
159
  requirements:
160
160
  - - ">="