graphql_rails 3.1.0 → 3.1.1

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: afbec95cbbadb5f167ecc59f8e21fd4e7ab4285f97a6d6bc847129c2de03fe43
4
- data.tar.gz: dc1434040422eda6fe0dca6ba123e6ff51a37df658bcd314be834f67c97f9d66
3
+ metadata.gz: f8680cd313b14bca588ff49b88021fbe2b2473b982ed58bbc7630aa8c47631ff
4
+ data.tar.gz: c8cc53c1e9b2ad49b494a2760c98743ce156a7c83597e1ddb261fe170851db41
5
5
  SHA512:
6
- metadata.gz: 57801abd718d1e5bac281e01a6dfa7e54bc3da9def20f479c6c028b5b8ab8e77dbc7cd2c7e6c6a1ff6ba48cfbc7e81e0b23bb6da81f40050fbc69d6ed460af3a
7
- data.tar.gz: 23c740466516ec437da7d7a8d909958b63d3aaca75dc3c53d748f5c7c79097c8c86c801396f4ba9e95b8fd16ae5f8cbcb9f59dcf06e0f69050cfcdc1e0ddb0cc
6
+ metadata.gz: 59ea863201a837dca103a4dc3329e66ae2c7f6fb29e779bca46cebcc016e8c38f6daedc93ebfd10ac9cf344290f4932cb43e3ee94f0726513e7659ae48414fa2
7
+ data.tar.gz: 4239e644a647bc8e0af11d144804f684ec6cd7aa1312a467916cdb83e9ed799d53e468db4ca62f4a415c23b5dbbb570cb4a1ca3552e86ea133f66efb72838f13
data/CHANGELOG.md CHANGED
@@ -9,6 +9,13 @@ 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.1](2026-10-20)
13
+
14
+ * Changed: do not throw "Cannot return null for non-nullable" error when errors are manually rendered
15
+ * Added: allow to specify type error hooks in router
16
+ * Added: `response.context` in RSpec controller helpers
17
+ * Added: `dig` on the RSpec controller helpers test context, as on `GraphQL::Query::Context`
18
+
12
19
  ## [3.1.0](2025-05-26)
13
20
 
14
21
  * Added: Allow passing custom decorator build strategy
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- graphql_rails (3.0.0)
4
+ graphql_rails (3.1.1)
5
5
  activesupport (>= 4)
6
6
  graphql (~> 2)
7
7
 
@@ -81,16 +81,16 @@ GEM
81
81
  diff-lcs (1.6.1)
82
82
  docile (1.4.1)
83
83
  erubi (1.13.1)
84
- fiber-storage (1.0.0)
84
+ fiber-storage (1.0.1)
85
85
  globalid (1.2.1)
86
86
  activesupport (>= 6.1)
87
- graphql (2.4.15)
87
+ graphql (2.5.11)
88
88
  base64
89
89
  fiber-storage
90
90
  logger
91
91
  i18n (1.14.7)
92
92
  concurrent-ruby (~> 1.0)
93
- logger (1.6.6)
93
+ logger (1.7.0)
94
94
  loofah (2.24.0)
95
95
  crass (~> 1.0.2)
96
96
  nokogiri (>= 1.12.0)
@@ -102,7 +102,7 @@ GEM
102
102
  marcel (1.0.4)
103
103
  method_source (1.1.0)
104
104
  mini_mime (1.1.5)
105
- mini_portile2 (2.8.8)
105
+ mini_portile2 (2.8.9)
106
106
  minitest (5.25.5)
107
107
  mongo (2.21.0)
108
108
  bson (>= 4.14.1, < 6.0.0)
@@ -110,7 +110,7 @@ GEM
110
110
  activemodel (>= 5.1, < 8.1, != 7.0.0)
111
111
  concurrent-ruby (>= 1.0.5, < 2.0)
112
112
  mongo (>= 2.18.0, < 3.0.0)
113
- net-imap (0.5.6)
113
+ net-imap (0.5.7)
114
114
  date
115
115
  net-protocol
116
116
  net-pop (0.1.2)
@@ -120,7 +120,7 @@ GEM
120
120
  net-smtp (0.5.1)
121
121
  net-protocol
122
122
  nio4r (2.7.4)
123
- nokogiri (1.18.6)
123
+ nokogiri (1.18.9)
124
124
  mini_portile2 (~> 2.8.2)
125
125
  racc (~> 1.4)
126
126
  parallel (1.26.3)
@@ -135,7 +135,7 @@ GEM
135
135
  byebug (~> 11.0)
136
136
  pry (>= 0.13, < 0.15)
137
137
  racc (1.8.1)
138
- rack (2.2.13)
138
+ rack (2.2.20)
139
139
  rack-test (2.2.0)
140
140
  rack (>= 1.3)
141
141
  rails (6.1.7.10)
@@ -169,7 +169,7 @@ GEM
169
169
  rainbow (3.1.1)
170
170
  rake (13.2.1)
171
171
  regexp_parser (2.10.0)
172
- rexml (3.4.1)
172
+ rexml (3.4.2)
173
173
  rspec (3.13.0)
174
174
  rspec-core (~> 3.13.0)
175
175
  rspec-expectations (~> 3.13.0)
@@ -174,3 +174,29 @@ end
174
174
  ```
175
175
 
176
176
  If you want to access raw graphql schema, you can call `GraphqlRouter.graphql_schema(:mobile)`
177
+
178
+ ## _before_type_error_
179
+
180
+ Sometimes it's handy to log or perform other actions when a GraphQL type error occurs. To do so, specify the Router.before_type_error hook:
181
+
182
+ ```ruby
183
+ GraphqlRails::Router.draw do
184
+ before_type_error do |type_error, context|
185
+ MyCustomExceptionLogger.call(type_error)
186
+ end
187
+ end
188
+ ```
189
+
190
+ Note: This might log `GraphQL::InvalidNullError` errors that are not visible to the end user. If you do not want that, use Router.after_type_error.
191
+
192
+ ## _after_type_error_
193
+
194
+ Sometimes it's handy to perform logging or other actions after a GraphQL type error occurs. To do so, specify the Router.after_type_error hook:
195
+
196
+ ```ruby
197
+ GraphqlRails::Router.draw do
198
+ after_type_error do |type_error, context|
199
+ MyCustomExceptionLogger.call(type_error)
200
+ end
201
+ end
202
+ ```
@@ -22,7 +22,7 @@ There are 3 helper methods:
22
22
 
23
23
  * `mutation(:your_controller_action_name, params: {}, context: {})`. `params` and `context` are optional
24
24
  * `query(:your_controller_action_name, params: {}, context: {})`. `params` and `context` are optional
25
- * `response`. Response is set only after you call `mutation` or `query`
25
+ * `response`. Response is set only after you call `mutation` or `query`. It exposes, among others, `result`, `errors`, `success?`, `controller`, `action_name` and `context`: the hash-like test context the action ran with (it supports `[]`, `fetch`, `key?`, `dig` and `to_h`), not a `GraphQL::Query::Context`
26
26
 
27
27
  ### Test examples
28
28
 
@@ -4,6 +4,10 @@ module GraphqlRails
4
4
  class Controller
5
5
  # runs {before/around/after}_action controller hooks
6
6
  class HandleControllerError
7
+ def self.call(error:, controller:)
8
+ new(error: error, controller: controller).call
9
+ end
10
+
7
11
  def initialize(error:, controller:)
8
12
  @error = error
9
13
  @controller = controller
@@ -20,11 +24,15 @@ module GraphqlRails
20
24
  attr_reader :error, :controller
21
25
 
22
26
  def render_unhandled_error(error)
23
- return render(error: error) if error.is_a?(GraphQL::ExecutionError)
27
+ return handle_graphql_execution_error(error) if error.is_a?(GraphQL::ExecutionError)
24
28
 
25
29
  render(error: SystemError.new(error))
26
30
  end
27
31
 
32
+ def handle_graphql_execution_error(error)
33
+ raise error
34
+ end
35
+
28
36
  def custom_handle_error
29
37
  return unless custom_handler
30
38
 
@@ -13,6 +13,8 @@ module GraphqlRails
13
13
  # base class for all graphql_rails controllers
14
14
  class Controller
15
15
  class << self
16
+ attr_accessor :error_handler
17
+
16
18
  def inherited(subclass)
17
19
  super
18
20
  new_config = controller_configuration.dup_with(controller: subclass)
@@ -79,6 +81,7 @@ module GraphqlRails
79
81
  object = errors.empty? ? object_or_errors : nil
80
82
 
81
83
  graphql_request.errors = errors
84
+ graphql_request.context[:rendered_errors] = true unless errors.empty?
82
85
  graphql_request.object_to_return = object
83
86
  end
84
87
 
@@ -94,7 +97,8 @@ module GraphqlRails
94
97
 
95
98
  render response if graphql_request.no_object_to_return?
96
99
  rescue StandardError => e
97
- HandleControllerError.new(error: e, controller: self).call
100
+ error_handler = self.class.error_handler || HandleControllerError
101
+ error_handler.call(error: e, controller: self)
98
102
  end
99
103
 
100
104
  def graphql_errors_from_render_params(rendering_params)
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'graphql/pagination/active_record_relation_connection'
4
+ require 'graphql_rails/decorator/relation_decorator'
5
+ require 'graphql_rails/router/plain_cursor_encoder'
6
+
7
+ module GraphqlRails
8
+ class Router
9
+ # Builds GraphQL::Schema based on previously defined GraphQL data.
10
+ # Also handles type error hooks (before_type_error, after_type_error)
11
+ # and implements logic for skipping null errors.
12
+ class Schema < ::GraphQL::Schema
13
+ use GraphQL::Schema::Visibility
14
+
15
+ connections.add(
16
+ GraphqlRails::Decorator::RelationDecorator,
17
+ GraphQL::Pagination::ActiveRecordRelationConnection
18
+ )
19
+
20
+ cursor_encoder(Router::PlainCursorEncoder)
21
+
22
+ def self.before_type_error(&block)
23
+ @before_type_error = block if block_given?
24
+ @before_type_error
25
+ end
26
+
27
+ def self.after_type_error(&block)
28
+ @after_type_error = block if block_given?
29
+ @after_type_error
30
+ end
31
+
32
+ def self.type_error(type_error, context)
33
+ before_type_error&.call(type_error, context)
34
+
35
+ return nil if type_error.is_a?(GraphQL::InvalidNullError) && context[:rendered_errors]
36
+
37
+ super.tap do
38
+ after_type_error&.call(type_error, context)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'graphql_rails/router/schema'
4
+
3
5
  module GraphqlRails
4
6
  class Router
5
7
  # builds GraphQL::Schema based on previously defined grahiti data
@@ -31,14 +33,7 @@ module GraphqlRails
31
33
 
32
34
  # rubocop:disable Metrics/MethodLength
33
35
  def define_schema_class(query_type, mutation_type, subscription_type, raw)
34
- Class.new(GraphQL::Schema) do
35
- use GraphQL::Schema::Visibility
36
-
37
- connections.add(
38
- GraphqlRails::Decorator::RelationDecorator,
39
- GraphQL::Pagination::ActiveRecordRelationConnection
40
- )
41
- cursor_encoder(Router::PlainCursorEncoder)
36
+ Class.new(GraphqlRails::Router::Schema) do
42
37
  raw.each { |action| send(action[:name], *action[:args], **action[:kwargs], &action[:block]) }
43
38
 
44
39
  query(query_type) if query_type
@@ -13,6 +13,7 @@ module GraphqlRails
13
13
  class Router
14
14
  RAW_ACTION_NAMES = %i[
15
15
  use rescue_from query_analyzer instrument cursor_encoder default_max_page_size tracer trace_with
16
+ before_type_error after_type_error
16
17
  ].freeze
17
18
 
18
19
  def self.draw(&block)
@@ -54,6 +54,10 @@ module GraphqlRails
54
54
  request.action_name
55
55
  end
56
56
 
57
+ def context
58
+ request.context
59
+ end
60
+
57
61
  private
58
62
 
59
63
  attr_reader :request
@@ -65,7 +69,7 @@ module GraphqlRails
65
69
 
66
70
  attr_reader :schema
67
71
 
68
- def_delegators :@provided_values, :[], :[]=, :to_h, :key?, :fetch
72
+ def_delegators :@provided_values, :[], :[]=, :to_h, :key?, :fetch, :dig
69
73
 
70
74
  def initialize(values:, schema:)
71
75
  @errors = []
@@ -78,6 +82,15 @@ module GraphqlRails
78
82
  end
79
83
  end
80
84
 
85
+ # Custom error handler to avoid raising errors in controller tests
86
+ class TestControllerErrorHandler < GraphqlRails::Controller::HandleControllerError
87
+ private
88
+
89
+ def handle_graphql_execution_error(error)
90
+ render(error: error)
91
+ end
92
+ end
93
+
81
94
  class SingleControllerSchemaBuilder
82
95
  attr_reader :controller
83
96
 
@@ -117,7 +130,11 @@ module GraphqlRails
117
130
  schema_builder = SingleControllerSchemaBuilder.new(described_class)
118
131
  context_object = FakeContext.new(values: context, schema: schema_builder.call)
119
132
  request = Request.new(params, context_object, controller: described_class, action_name: query_name)
133
+ original_error_handler = described_class.error_handler
134
+
135
+ described_class.error_handler = TestControllerErrorHandler
120
136
  described_class.new(request).call(query_name)
137
+ described_class.error_handler = original_error_handler
121
138
 
122
139
  @response = Response.new(request)
123
140
  @response
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GraphqlRails
4
- VERSION = '3.1.0'
4
+ VERSION = '3.1.1'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 3.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Povilas Jurčys
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-05-26 00:00:00.000000000 Z
11
+ date: 2026-10-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: graphql
@@ -222,6 +222,7 @@ files:
222
222
  - lib/graphql_rails/router/query_route.rb
223
223
  - lib/graphql_rails/router/resource_routes_builder.rb
224
224
  - lib/graphql_rails/router/route.rb
225
+ - lib/graphql_rails/router/schema.rb
225
226
  - lib/graphql_rails/router/schema_builder.rb
226
227
  - lib/graphql_rails/rspec_controller_helpers.rb
227
228
  - lib/graphql_rails/tasks/dump_graphql_schema.rb