graphql_preload_queries 0.3.1 → 0.4.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 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
  - - ">="