graphql_rails 3.0.0 → 3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 47c75badc8873658f461e2bc0f6de0ca35f2c13c7ded2ed66b23b20ee91fc60e
4
- data.tar.gz: 551a92383fad945d6fb8c03f190793431b485a8a98256a64e26f892c1e48fc2f
3
+ metadata.gz: afbec95cbbadb5f167ecc59f8e21fd4e7ab4285f97a6d6bc847129c2de03fe43
4
+ data.tar.gz: dc1434040422eda6fe0dca6ba123e6ff51a37df658bcd314be834f67c97f9d66
5
5
  SHA512:
6
- metadata.gz: 0e852e9c89ee080ca786abfaabea1162d8ed1eadb4086bf7d2f9908c454e56dc8c839ab05f6a3967859188f3c36f32eae1907b45e41476e24fb81f5fb5db8e29
7
- data.tar.gz: 0d970a75c022b4635e6c925db92f8d7d22cc67b8e8e41ed8c961c98b2a8aa2c3b4726a29fc736af5151ea935c899b21d454e9af703e9beb6ea9fab378d5fecbf
6
+ metadata.gz: 57801abd718d1e5bac281e01a6dfa7e54bc3da9def20f479c6c028b5b8ab8e77dbc7cd2c7e6c6a1ff6ba48cfbc7e81e0b23bb6da81f40050fbc69d6ed460af3a
7
+ data.tar.gz: 23c740466516ec437da7d7a8d909958b63d3aaca75dc3c53d748f5c7c79097c8c86c801396f4ba9e95b8fd16ae5f8cbcb9f59dcf06e0f69050cfcdc1e0ddb0cc
@@ -5,7 +5,7 @@ jobs:
5
5
  strategy:
6
6
  fail-fast: false
7
7
  matrix:
8
- ruby-version: ['3.0', '3.1', '3.2', '3.3']
8
+ ruby-version: ["3.1", "3.2", "3.3"]
9
9
 
10
10
  runs-on: ubuntu-latest
11
11
  env:
data/CHANGELOG.md CHANGED
@@ -9,6 +9,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
 
10
10
  * Added/Changed/Deprecated/Removed/Fixed/Security: YOUR CHANGE HERE
11
11
 
12
+ ## [3.1.0](2025-05-26)
13
+
14
+ * Added: Allow passing custom decorator build strategy
15
+ * Added: Tracer support to router
16
+ * Fixed: Better handle render in controller hooks
17
+ * Fixed: Reduce memory allocations when defining attributes
18
+ * Updated: GraphQL and gems version dependencies
19
+ * Updated: Bump rexml from 3.2.8 to 3.3.9
20
+
12
21
  ## [3.0.0](2024-05-31)
13
22
 
14
23
  * Added: `input.attribute.property` method which allows aliasing input parameter keys
data/Gemfile.lock CHANGED
@@ -3,165 +3,186 @@ PATH
3
3
  specs:
4
4
  graphql_rails (3.0.0)
5
5
  activesupport (>= 4)
6
- graphql (= 2.1.7)
6
+ graphql (~> 2)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- actioncable (6.1.7.1)
12
- actionpack (= 6.1.7.1)
13
- activesupport (= 6.1.7.1)
11
+ actioncable (6.1.7.10)
12
+ actionpack (= 6.1.7.10)
13
+ activesupport (= 6.1.7.10)
14
14
  nio4r (~> 2.0)
15
15
  websocket-driver (>= 0.6.1)
16
- actionmailbox (6.1.7.1)
17
- actionpack (= 6.1.7.1)
18
- activejob (= 6.1.7.1)
19
- activerecord (= 6.1.7.1)
20
- activestorage (= 6.1.7.1)
21
- activesupport (= 6.1.7.1)
16
+ actionmailbox (6.1.7.10)
17
+ actionpack (= 6.1.7.10)
18
+ activejob (= 6.1.7.10)
19
+ activerecord (= 6.1.7.10)
20
+ activestorage (= 6.1.7.10)
21
+ activesupport (= 6.1.7.10)
22
22
  mail (>= 2.7.1)
23
- actionmailer (6.1.7.1)
24
- actionpack (= 6.1.7.1)
25
- actionview (= 6.1.7.1)
26
- activejob (= 6.1.7.1)
27
- activesupport (= 6.1.7.1)
23
+ actionmailer (6.1.7.10)
24
+ actionpack (= 6.1.7.10)
25
+ actionview (= 6.1.7.10)
26
+ activejob (= 6.1.7.10)
27
+ activesupport (= 6.1.7.10)
28
28
  mail (~> 2.5, >= 2.5.4)
29
29
  rails-dom-testing (~> 2.0)
30
- actionpack (6.1.7.1)
31
- actionview (= 6.1.7.1)
32
- activesupport (= 6.1.7.1)
30
+ actionpack (6.1.7.10)
31
+ actionview (= 6.1.7.10)
32
+ activesupport (= 6.1.7.10)
33
33
  rack (~> 2.0, >= 2.0.9)
34
34
  rack-test (>= 0.6.3)
35
35
  rails-dom-testing (~> 2.0)
36
36
  rails-html-sanitizer (~> 1.0, >= 1.2.0)
37
- actiontext (6.1.7.1)
38
- actionpack (= 6.1.7.1)
39
- activerecord (= 6.1.7.1)
40
- activestorage (= 6.1.7.1)
41
- activesupport (= 6.1.7.1)
37
+ actiontext (6.1.7.10)
38
+ actionpack (= 6.1.7.10)
39
+ activerecord (= 6.1.7.10)
40
+ activestorage (= 6.1.7.10)
41
+ activesupport (= 6.1.7.10)
42
42
  nokogiri (>= 1.8.5)
43
- actionview (6.1.7.1)
44
- activesupport (= 6.1.7.1)
43
+ actionview (6.1.7.10)
44
+ activesupport (= 6.1.7.10)
45
45
  builder (~> 3.1)
46
46
  erubi (~> 1.4)
47
47
  rails-dom-testing (~> 2.0)
48
48
  rails-html-sanitizer (~> 1.1, >= 1.2.0)
49
- activejob (6.1.7.1)
50
- activesupport (= 6.1.7.1)
49
+ activejob (6.1.7.10)
50
+ activesupport (= 6.1.7.10)
51
51
  globalid (>= 0.3.6)
52
- activemodel (6.1.7.1)
53
- activesupport (= 6.1.7.1)
54
- activerecord (6.1.7.1)
55
- activemodel (= 6.1.7.1)
56
- activesupport (= 6.1.7.1)
57
- activestorage (6.1.7.1)
58
- actionpack (= 6.1.7.1)
59
- activejob (= 6.1.7.1)
60
- activerecord (= 6.1.7.1)
61
- activesupport (= 6.1.7.1)
52
+ activemodel (6.1.7.10)
53
+ activesupport (= 6.1.7.10)
54
+ activerecord (6.1.7.10)
55
+ activemodel (= 6.1.7.10)
56
+ activesupport (= 6.1.7.10)
57
+ activestorage (6.1.7.10)
58
+ actionpack (= 6.1.7.10)
59
+ activejob (= 6.1.7.10)
60
+ activerecord (= 6.1.7.10)
61
+ activesupport (= 6.1.7.10)
62
62
  marcel (~> 1.0)
63
63
  mini_mime (>= 1.1.0)
64
- activesupport (6.1.7.1)
64
+ activesupport (6.1.7.10)
65
65
  concurrent-ruby (~> 1.0, >= 1.0.2)
66
66
  i18n (>= 1.6, < 2)
67
67
  minitest (>= 5.1)
68
68
  tzinfo (~> 2.0)
69
69
  zeitwerk (~> 2.3)
70
- ast (2.4.2)
71
- bson (4.14.0)
72
- builder (3.2.4)
70
+ ast (2.4.3)
71
+ base64 (0.2.0)
72
+ bson (5.0.2)
73
+ builder (3.3.0)
73
74
  byebug (11.1.3)
74
75
  codecov (0.6.0)
75
76
  simplecov (>= 0.15, < 0.22)
76
77
  coderay (1.1.3)
77
- concurrent-ruby (1.3.1)
78
+ concurrent-ruby (1.3.5)
78
79
  crass (1.0.6)
79
- diff-lcs (1.5.0)
80
- docile (1.4.0)
81
- erubi (1.10.0)
82
- globalid (1.0.1)
83
- activesupport (>= 5.0)
84
- graphql (2.1.7)
85
- racc (~> 1.4)
86
- i18n (1.14.5)
80
+ date (3.4.1)
81
+ diff-lcs (1.6.1)
82
+ docile (1.4.1)
83
+ erubi (1.13.1)
84
+ fiber-storage (1.0.0)
85
+ globalid (1.2.1)
86
+ activesupport (>= 6.1)
87
+ graphql (2.4.15)
88
+ base64
89
+ fiber-storage
90
+ logger
91
+ i18n (1.14.7)
87
92
  concurrent-ruby (~> 1.0)
88
- loofah (2.19.1)
93
+ logger (1.6.6)
94
+ loofah (2.24.0)
89
95
  crass (~> 1.0.2)
90
- nokogiri (>= 1.5.9)
91
- mail (2.7.1)
96
+ nokogiri (>= 1.12.0)
97
+ mail (2.8.1)
92
98
  mini_mime (>= 0.1.1)
93
- marcel (1.0.2)
94
- method_source (1.0.0)
95
- mini_mime (1.1.2)
96
- mini_portile2 (2.8.6)
97
- minitest (5.23.1)
98
- mongo (2.17.0)
99
- bson (>= 4.8.2, < 5.0.0)
100
- mongoid (7.3.3)
101
- activemodel (>= 5.1, < 6.2)
102
- mongo (>= 2.10.5, < 3.0.0)
103
- ruby2_keywords (~> 0.0.5)
104
- nio4r (2.5.8)
105
- nokogiri (1.16.5)
99
+ net-imap
100
+ net-pop
101
+ net-smtp
102
+ marcel (1.0.4)
103
+ method_source (1.1.0)
104
+ mini_mime (1.1.5)
105
+ mini_portile2 (2.8.8)
106
+ minitest (5.25.5)
107
+ mongo (2.21.0)
108
+ bson (>= 4.14.1, < 6.0.0)
109
+ mongoid (9.0.6)
110
+ activemodel (>= 5.1, < 8.1, != 7.0.0)
111
+ concurrent-ruby (>= 1.0.5, < 2.0)
112
+ mongo (>= 2.18.0, < 3.0.0)
113
+ net-imap (0.5.6)
114
+ date
115
+ net-protocol
116
+ net-pop (0.1.2)
117
+ net-protocol
118
+ net-protocol (0.2.2)
119
+ timeout
120
+ net-smtp (0.5.1)
121
+ net-protocol
122
+ nio4r (2.7.4)
123
+ nokogiri (1.18.6)
106
124
  mini_portile2 (~> 2.8.2)
107
125
  racc (~> 1.4)
108
- parallel (1.21.0)
109
- parser (3.1.0.0)
126
+ parallel (1.26.3)
127
+ parser (3.3.7.3)
110
128
  ast (~> 2.4.1)
111
- pry (0.13.1)
129
+ racc
130
+ prism (1.4.0)
131
+ pry (0.14.2)
112
132
  coderay (~> 1.1)
113
133
  method_source (~> 1.0)
114
- pry-byebug (3.9.0)
134
+ pry-byebug (3.10.1)
115
135
  byebug (~> 11.0)
116
- pry (~> 0.13.0)
117
- racc (1.8.0)
118
- rack (2.2.9)
119
- rack-test (1.1.0)
120
- rack (>= 1.0, < 3)
121
- rails (6.1.7.1)
122
- actioncable (= 6.1.7.1)
123
- actionmailbox (= 6.1.7.1)
124
- actionmailer (= 6.1.7.1)
125
- actionpack (= 6.1.7.1)
126
- actiontext (= 6.1.7.1)
127
- actionview (= 6.1.7.1)
128
- activejob (= 6.1.7.1)
129
- activemodel (= 6.1.7.1)
130
- activerecord (= 6.1.7.1)
131
- activestorage (= 6.1.7.1)
132
- activesupport (= 6.1.7.1)
136
+ pry (>= 0.13, < 0.15)
137
+ racc (1.8.1)
138
+ rack (2.2.13)
139
+ rack-test (2.2.0)
140
+ rack (>= 1.3)
141
+ rails (6.1.7.10)
142
+ actioncable (= 6.1.7.10)
143
+ actionmailbox (= 6.1.7.10)
144
+ actionmailer (= 6.1.7.10)
145
+ actionpack (= 6.1.7.10)
146
+ actiontext (= 6.1.7.10)
147
+ actionview (= 6.1.7.10)
148
+ activejob (= 6.1.7.10)
149
+ activemodel (= 6.1.7.10)
150
+ activerecord (= 6.1.7.10)
151
+ activestorage (= 6.1.7.10)
152
+ activesupport (= 6.1.7.10)
133
153
  bundler (>= 1.15.0)
134
- railties (= 6.1.7.1)
154
+ railties (= 6.1.7.10)
135
155
  sprockets-rails (>= 2.0.0)
136
- rails-dom-testing (2.0.3)
137
- activesupport (>= 4.2.0)
156
+ rails-dom-testing (2.2.0)
157
+ activesupport (>= 5.0.0)
158
+ minitest
138
159
  nokogiri (>= 1.6)
139
- rails-html-sanitizer (1.4.4)
140
- loofah (~> 2.19, >= 2.19.1)
141
- railties (6.1.7.1)
142
- actionpack (= 6.1.7.1)
143
- activesupport (= 6.1.7.1)
160
+ rails-html-sanitizer (1.6.2)
161
+ loofah (~> 2.21)
162
+ nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
163
+ railties (6.1.7.10)
164
+ actionpack (= 6.1.7.10)
165
+ activesupport (= 6.1.7.10)
144
166
  method_source
145
167
  rake (>= 12.2)
146
168
  thor (~> 1.0)
147
169
  rainbow (3.1.1)
148
- rake (13.0.6)
149
- regexp_parser (2.2.0)
150
- rexml (3.2.8)
151
- strscan (>= 3.0.9)
152
- rspec (3.10.0)
153
- rspec-core (~> 3.10.0)
154
- rspec-expectations (~> 3.10.0)
155
- rspec-mocks (~> 3.10.0)
156
- rspec-core (3.10.1)
157
- rspec-support (~> 3.10.0)
158
- rspec-expectations (3.10.2)
170
+ rake (13.2.1)
171
+ regexp_parser (2.10.0)
172
+ rexml (3.4.1)
173
+ rspec (3.13.0)
174
+ rspec-core (~> 3.13.0)
175
+ rspec-expectations (~> 3.13.0)
176
+ rspec-mocks (~> 3.13.0)
177
+ rspec-core (3.13.3)
178
+ rspec-support (~> 3.13.0)
179
+ rspec-expectations (3.13.3)
159
180
  diff-lcs (>= 1.2.0, < 2.0)
160
- rspec-support (~> 3.10.0)
161
- rspec-mocks (3.10.2)
181
+ rspec-support (~> 3.13.0)
182
+ rspec-mocks (3.13.2)
162
183
  diff-lcs (>= 1.2.0, < 2.0)
163
- rspec-support (~> 3.10.0)
164
- rspec-support (3.10.3)
184
+ rspec-support (~> 3.13.0)
185
+ rspec-support (3.13.2)
165
186
  rubocop (1.5.2)
166
187
  parallel (~> 1.10)
167
188
  parser (>= 2.7.1.5)
@@ -171,38 +192,39 @@ GEM
171
192
  rubocop-ast (>= 1.2.0, < 2.0)
172
193
  ruby-progressbar (~> 1.7)
173
194
  unicode-display_width (>= 1.4.0, < 2.0)
174
- rubocop-ast (1.15.1)
175
- parser (>= 3.0.1.1)
195
+ rubocop-ast (1.43.0)
196
+ parser (>= 3.3.7.2)
197
+ prism (~> 1.4)
176
198
  rubocop-performance (1.10.2)
177
199
  rubocop (>= 0.90.0, < 2.0)
178
200
  rubocop-ast (>= 0.4.0)
179
201
  rubocop-rspec (2.4.0)
180
202
  rubocop (~> 1.0)
181
203
  rubocop-ast (>= 1.1.0)
182
- ruby-progressbar (1.11.0)
183
- ruby2_keywords (0.0.5)
204
+ ruby-progressbar (1.13.0)
184
205
  simplecov (0.21.2)
185
206
  docile (~> 1.1)
186
207
  simplecov-html (~> 0.11)
187
208
  simplecov_json_formatter (~> 0.1)
188
- simplecov-html (0.12.3)
189
- simplecov_json_formatter (0.1.3)
190
- sprockets (4.0.2)
209
+ simplecov-html (0.13.1)
210
+ simplecov_json_formatter (0.1.4)
211
+ sprockets (4.2.1)
191
212
  concurrent-ruby (~> 1.0)
192
- rack (> 1, < 3)
193
- sprockets-rails (3.4.2)
194
- actionpack (>= 5.2)
195
- activesupport (>= 5.2)
213
+ rack (>= 2.2.4, < 4)
214
+ sprockets-rails (3.5.2)
215
+ actionpack (>= 6.1)
216
+ activesupport (>= 6.1)
196
217
  sprockets (>= 3.0.0)
197
- strscan (3.1.0)
198
- thor (1.2.1)
218
+ thor (1.3.2)
219
+ timeout (0.4.3)
199
220
  tzinfo (2.0.6)
200
221
  concurrent-ruby (~> 1.0)
201
222
  unicode-display_width (1.8.0)
202
- websocket-driver (0.7.5)
223
+ websocket-driver (0.7.7)
224
+ base64
203
225
  websocket-extensions (>= 0.1.0)
204
226
  websocket-extensions (0.1.5)
205
- zeitwerk (2.6.15)
227
+ zeitwerk (2.6.18)
206
228
 
207
229
  PLATFORMS
208
230
  ruby
@@ -25,7 +25,7 @@ class CommentDecorator < SimpleDelegator
25
25
  end
26
26
  ```
27
27
 
28
- In order to decorate object with exra arguments, simply pass them to `.decorate` method. Like this:
28
+ In order to decorate object with extra arguments, simply pass them to `.decorate` method. Like this:
29
29
 
30
30
  ```ruby
31
31
  CommentDecorator.decorate(comment, current_user)
@@ -67,3 +67,33 @@ class UsersController < GraphqlRails::Controller
67
67
  end
68
68
  end
69
69
  ```
70
+
71
+ ## Decorating with custom method
72
+
73
+ Sometimes building decorator instance is not that straight-forward and you need to use custom build strategy. In such cases you can pass `build_with: :DESIRED_CLASS_METHOD` option:
74
+
75
+ ```ruby
76
+ class UserDecorator < SimpleDelegator
77
+ include GraphqlRails::Model
78
+ include GraphqlRails::Decorator
79
+ # ...
80
+
81
+ def self.custom_build(user)
82
+ user.admin? ? new(user, admin: true) : new(user)
83
+ end
84
+
85
+ def initialize(user, admin: false)
86
+ @user = user
87
+ @admin = admin
88
+ end
89
+ end
90
+
91
+ class UsersController < GraphqlRails::Controller
92
+ action(:index).paginated.returns('[UserDecorator!]!')
93
+
94
+ def index
95
+ users = User.where(active: true)
96
+ UserDecorator.decorate(user, build_with: :custom_build)
97
+ end
98
+ end
99
+ ```
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
20
20
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
21
  spec.require_paths = ['lib']
22
22
 
23
- spec.add_dependency 'graphql', '2.1.7'
23
+ spec.add_dependency 'graphql', '~> 2'
24
24
  spec.add_dependency 'activesupport', '>= 4'
25
25
 
26
26
  spec.add_development_dependency 'bundler', '~> 2'
@@ -8,11 +8,7 @@ module GraphqlRails
8
8
 
9
9
  class_methods do
10
10
  def call(*args, **kwargs, &block)
11
- if kwargs.present?
12
- new(*args, **kwargs).call(&block)
13
- else
14
- new(*args).call(&block)
15
- end
11
+ new(*args, **kwargs).call(&block)
16
12
  end
17
13
  end
18
14
  end
@@ -4,9 +4,10 @@ module GraphqlRails
4
4
  class Controller
5
5
  # runs {before/around/after}_action controller hooks
6
6
  class ActionHooksRunner
7
- def initialize(action_name:, controller:)
7
+ def initialize(action_name:, controller:, graphql_request:)
8
8
  @action_name = action_name
9
9
  @controller = controller
10
+ @graphql_request = graphql_request
10
11
  end
11
12
 
12
13
  def call(&block)
@@ -19,7 +20,7 @@ module GraphqlRails
19
20
 
20
21
  private
21
22
 
22
- attr_reader :action_name, :controller
23
+ attr_reader :action_name, :controller, :graphql_request
23
24
 
24
25
  def all_around_hooks
25
26
  controller_configuration.action_hooks_for(:around, action_name)
@@ -30,6 +31,8 @@ module GraphqlRails
30
31
  end
31
32
 
32
33
  def run_around_action_hooks(around_hooks = all_around_hooks, &block)
34
+ return if graphql_request.errors.any?
35
+
33
36
  pending_around_hooks = around_hooks.clone
34
37
  action_hook = pending_around_hooks.shift
35
38
 
@@ -41,6 +44,8 @@ module GraphqlRails
41
44
  end
42
45
 
43
46
  def execute_hook(action_hook, &block)
47
+ return if graphql_request.errors.any?
48
+
44
49
  if action_hook.anonymous?
45
50
  controller.instance_exec(controller, *block, &action_hook.action_proc)
46
51
  else
@@ -14,6 +14,7 @@ module GraphqlRails
14
14
  @inputs = inputs.except(:lookahead)
15
15
  @lookahead = inputs[:lookahead]
16
16
  @context = context
17
+ @errors = []
17
18
  end
18
19
 
19
20
  def errors=(new_errors)
@@ -89,7 +89,7 @@ module GraphqlRails
89
89
  private
90
90
 
91
91
  def call_with_rendering
92
- hooks_runner = ActionHooksRunner.new(action_name: action_name, controller: self)
92
+ hooks_runner = ActionHooksRunner.new(action_name: action_name, controller: self, graphql_request: graphql_request)
93
93
  response = hooks_runner.call { public_send(action_name) }
94
94
 
95
95
  render response if graphql_request.no_object_to_return?
@@ -12,11 +12,12 @@ module GraphqlRails
12
12
  defined?(Mongoid) && object.is_a?(Mongoid::Criteria)
13
13
  end
14
14
 
15
- def initialize(decorator:, relation:, decorator_args: [], decorator_kwargs: {})
15
+ def initialize(decorator:, relation:, decorator_args: [], decorator_kwargs: {}, build_with: :new)
16
16
  @relation = relation
17
17
  @decorator = decorator
18
18
  @decorator_args = decorator_args
19
19
  @decorator_kwargs = decorator_kwargs
20
+ @build_with = build_with
20
21
  end
21
22
 
22
23
  %i[where limit order group offset from select having all unscope].each do |method_name|
@@ -38,12 +39,12 @@ module GraphqlRails
38
39
  end
39
40
 
40
41
  def to_a
41
- @to_a ||= relation.to_a.map { |it| decorator.new(it, *decorator_args, **decorator_kwargs) }
42
+ @to_a ||= relation.to_a.map { |it| build_decorator(it, *decorator_args, **decorator_kwargs) }
42
43
  end
43
44
 
44
45
  private
45
46
 
46
- attr_reader :relation, :decorator, :decorator_args, :decorator_kwargs
47
+ attr_reader :relation, :decorator, :decorator_args, :decorator_kwargs, :build_with
47
48
 
48
49
  def decoratable_object_method(method_name, *args, **kwargs, &block)
49
50
  object = relation.public_send(method_name, *args, **kwargs, &block)
@@ -54,12 +55,16 @@ module GraphqlRails
54
55
  return object_or_list if object_or_list.blank?
55
56
 
56
57
  if object_or_list.is_a?(Array)
57
- object_or_list.map { |it| decorator.new(it, *decorator_args, **decorator_kwargs) }
58
+ object_or_list.map { |it| build_decorator(it, *decorator_args, **decorator_kwargs) }
58
59
  else
59
- decorator.new(object_or_list, *decorator_args, **decorator_kwargs)
60
+ build_decorator(object_or_list, *decorator_args, **decorator_kwargs)
60
61
  end
61
62
  end
62
63
 
64
+ def build_decorator(*args, **kwargs, &block)
65
+ decorator.public_send(build_with, *args, **kwargs, &block)
66
+ end
67
+
63
68
  def decoratable_block_method(method_name, *args, **kwargs)
64
69
  relation.public_send(method_name, *args, **kwargs) do |object, *other_args|
65
70
  decorated_object = decorate(object)
@@ -71,7 +76,8 @@ module GraphqlRails
71
76
  new_relation = relation.public_send(method_name, *args, **kwargs, &block)
72
77
  self.class.new(
73
78
  decorator: decorator, relation: new_relation,
74
- decorator_args: decorator_args, decorator_kwargs: decorator_kwargs
79
+ decorator_args: decorator_args, decorator_kwargs: decorator_kwargs,
80
+ build_with: build_with
75
81
  )
76
82
  end
77
83
  end
@@ -25,23 +25,27 @@ module GraphqlRails
25
25
  extend ActiveSupport::Concern
26
26
 
27
27
  class_methods do
28
- def decorate(object, *args, **kwargs)
28
+ def decorate(object, *args, build_with: :new, **kwargs)
29
29
  if Decorator::RelationDecorator.decorates?(object)
30
- decorate_with_relation_decorator(object, args, kwargs)
30
+ decorate_with_relation_decorator(object, args, kwargs, build_with: build_with)
31
31
  elsif object.nil?
32
32
  nil
33
33
  elsif object.is_a?(Array)
34
- object.map { |item| new(item, *args, **kwargs) }
34
+ object.map { |item| public_send(build_with, item, *args, **kwargs) }
35
35
  else
36
- new(object, *args, **kwargs)
36
+ public_send(build_with, object, *args, **kwargs)
37
37
  end
38
38
  end
39
39
 
40
40
  private
41
41
 
42
- def decorate_with_relation_decorator(object, args, kwargs)
42
+ def decorate_with_relation_decorator(object, args, kwargs, build_with:)
43
43
  Decorator::RelationDecorator.new(
44
- relation: object, decorator: self, decorator_args: args, decorator_kwargs: kwargs
44
+ relation: object,
45
+ decorator: self,
46
+ decorator_args: args,
47
+ decorator_kwargs: kwargs,
48
+ build_with: build_with
45
49
  )
46
50
  end
47
51
  end
@@ -6,6 +6,7 @@ module GraphqlRails
6
6
  class AddFieldsToGraphqlType
7
7
  require 'graphql_rails/concerns/service'
8
8
  require 'graphql_rails/model/call_graphql_model_method'
9
+ require 'graphql_rails/model/direct_field_resolver'
9
10
 
10
11
  include ::GraphqlRails::Service
11
12
 
@@ -31,7 +32,7 @@ module GraphqlRails
31
32
  end
32
33
 
33
34
  define_method(attribute.field_name) do |**kwargs|
34
- CallGraphqlModelMethod.call(
35
+ DirectFieldResolver.call(
35
36
  model: object,
36
37
  attribute_config: attribute,
37
38
  method_keyword_arguments: kwargs,
@@ -10,14 +10,24 @@ module GraphqlRails
10
10
 
11
11
  PAGINATION_KEYS = %i[before after first last].freeze
12
12
 
13
- def initialize(model:, method_keyword_arguments:, graphql_context:, attribute_config:)
13
+ @instance_cache = {}
14
+
15
+ class << self
16
+ attr_reader :instance_cache
17
+
18
+ def call(*_args, **kwargs)
19
+ cache_key = kwargs[:attribute_config].object_id
20
+ @instance_cache[cache_key] ||= new
21
+ @instance_cache[cache_key].call_with_args(**kwargs)
22
+ end
23
+ end
24
+
25
+ def call_with_args(model:, method_keyword_arguments:, graphql_context:, attribute_config:)
14
26
  @model = model
15
27
  @method_keyword_arguments = method_keyword_arguments
16
28
  @graphql_context = graphql_context
17
29
  @attribute_config = attribute_config
18
- end
19
30
 
20
- def call
21
31
  with_graphql_context do
22
32
  run_method
23
33
  end
@@ -59,7 +69,9 @@ module GraphqlRails
59
69
  def custom_keyword_arguments
60
70
  return method_keyword_arguments unless paginated?
61
71
 
62
- method_keyword_arguments.except(*PAGINATION_KEYS)
72
+ method_keyword_arguments.each_with_object({}) do |(key, value), result|
73
+ result[key] = value unless PAGINATION_KEYS.include?(key)
74
+ end
63
75
  end
64
76
 
65
77
  def with_graphql_context
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphqlRails
4
+ module Model
5
+ # Takes shortcuts for simple cases to minimize allocations
6
+ class DirectFieldResolver
7
+ class << self
8
+ def call(model:, attribute_config:, method_keyword_arguments:, graphql_context:)
9
+ property = attribute_config.property
10
+
11
+ if method_keyword_arguments.empty? && !attribute_config.paginated?
12
+ return simple_resolver(model: model, graphql_context: graphql_context, property: property)
13
+ end
14
+
15
+ CallGraphqlModelMethod.call(
16
+ model: model,
17
+ attribute_config: attribute_config,
18
+ method_keyword_arguments: method_keyword_arguments,
19
+ graphql_context: graphql_context
20
+ )
21
+ end
22
+
23
+ def simple_resolver(model:, graphql_context:, property:)
24
+ return model.send(property) unless model.respond_to?(:with_graphql_context)
25
+
26
+ model.with_graphql_context(graphql_context) { model.send(property) }
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -32,6 +32,8 @@ module GraphqlRails
32
32
  # rubocop:disable Metrics/MethodLength
33
33
  def define_schema_class(query_type, mutation_type, subscription_type, raw)
34
34
  Class.new(GraphQL::Schema) do
35
+ use GraphQL::Schema::Visibility
36
+
35
37
  connections.add(
36
38
  GraphqlRails::Decorator::RelationDecorator,
37
39
  GraphQL::Pagination::ActiveRecordRelationConnection
@@ -12,7 +12,7 @@ module GraphqlRails
12
12
  # graphql router that mimics Rails.application.routes
13
13
  class Router
14
14
  RAW_ACTION_NAMES = %i[
15
- use rescue_from query_analyzer instrument cursor_encoder default_max_page_size
15
+ use rescue_from query_analyzer instrument cursor_encoder default_max_page_size tracer trace_with
16
16
  ].freeze
17
17
 
18
18
  def self.draw(&block)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GraphqlRails
4
- VERSION = '3.0.0'
4
+ VERSION = '3.1.0'
5
5
  end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Povilas Jurčys
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-05-31 00:00:00.000000000 Z
11
+ date: 2025-05-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: graphql
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '='
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 2.1.7
19
+ version: '2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '='
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 2.1.7
26
+ version: '2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activesupport
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -122,7 +122,7 @@ dependencies:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
124
  version: '6'
125
- description:
125
+ description:
126
126
  email:
127
127
  - po.jurcys@gmail.com
128
128
  executables: []
@@ -207,6 +207,7 @@ files:
207
207
  - lib/graphql_rails/model/call_graphql_model_method.rb
208
208
  - lib/graphql_rails/model/configurable.rb
209
209
  - lib/graphql_rails/model/configuration.rb
210
+ - lib/graphql_rails/model/direct_field_resolver.rb
210
211
  - lib/graphql_rails/model/find_or_build_graphql_input_type.rb
211
212
  - lib/graphql_rails/model/find_or_build_graphql_type.rb
212
213
  - lib/graphql_rails/model/find_or_build_graphql_type_class.rb
@@ -236,7 +237,7 @@ homepage: https://github.com/samesystem/graphql_rails
236
237
  licenses:
237
238
  - MIT
238
239
  metadata: {}
239
- post_install_message:
240
+ post_install_message:
240
241
  rdoc_options: []
241
242
  require_paths:
242
243
  - lib
@@ -252,7 +253,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
252
253
  version: '0'
253
254
  requirements: []
254
255
  rubygems_version: 3.3.7
255
- signing_key:
256
+ signing_key:
256
257
  specification_version: 4
257
258
  summary: Rails style structure for GraphQL API.
258
259
  test_files: []