graphql 1.9.7 → 1.9.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/generators/graphql/install_generator.rb +2 -1
- data/lib/generators/graphql/templates/base_argument.erb +4 -0
- data/lib/generators/graphql/templates/base_field.erb +2 -0
- data/lib/generators/graphql/templates/base_input_object.erb +1 -0
- data/lib/graphql/analysis/ast/query_complexity.rb +34 -18
- data/lib/graphql/argument.rb +8 -2
- data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +1 -1
- data/lib/graphql/language/lexer.rb +24 -13
- data/lib/graphql/language/lexer.rl +23 -13
- data/lib/graphql/query/arguments.rb +16 -15
- data/lib/graphql/schema.rb +105 -48
- data/lib/graphql/schema/argument.rb +12 -1
- data/lib/graphql/schema/build_from_definition.rb +3 -0
- data/lib/graphql/schema/field.rb +3 -8
- data/lib/graphql/schema/find_inherited_value.rb +20 -0
- data/lib/graphql/schema/input_object.rb +1 -3
- data/lib/graphql/schema/loader.rb +1 -0
- data/lib/graphql/schema/member/base_dsl_methods.rb +7 -18
- data/lib/graphql/schema/member/has_arguments.rb +4 -9
- data/lib/graphql/schema/member/has_fields.rb +14 -0
- data/lib/graphql/schema/member/relay_shortcuts.rb +2 -2
- data/lib/graphql/schema/resolver.rb +31 -8
- data/lib/graphql/schema/resolver/has_payload_type.rb +3 -2
- data/lib/graphql/schema/subscription.rb +1 -1
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- data/spec/graphql/analysis/analyze_query_spec.rb +14 -25
- data/spec/graphql/analysis/ast/max_query_complexity_spec.rb +7 -19
- data/spec/graphql/analysis/ast/max_query_depth_spec.rb +5 -12
- data/spec/graphql/analysis/max_query_complexity_spec.rb +12 -20
- data/spec/graphql/analysis/max_query_depth_spec.rb +6 -13
- data/spec/graphql/language/lexer_spec.rb +19 -1
- data/spec/graphql/schema/argument_spec.rb +1 -1
- data/spec/graphql/schema/build_from_definition_spec.rb +10 -0
- data/spec/graphql/schema/catchall_middleware_spec.rb +6 -9
- data/spec/graphql/schema/input_object_spec.rb +25 -0
- data/spec/graphql/schema/loader_spec.rb +65 -1
- data/spec/graphql/schema/object_spec.rb +21 -0
- data/spec/graphql/schema/resolver_spec.rb +30 -1
- data/spec/graphql/schema_spec.rb +135 -0
- data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +25 -0
- data/spec/integration/rails/generators/graphql/install_generator_spec.rb +20 -0
- data/spec/integration/tmp/app/graphql/types/page_type.rb +5 -0
- data/spec/support/dummy/schema.rb +1 -1
- data/spec/support/lazy_helpers.rb +1 -1
- data/spec/support/parser/filename_example_invalid_utf8.graphql +1 -0
- metadata +10 -132
- data/spec/integration/tmp/app/graphql/types/date_type.rb +0 -14
- data/spec/integration/tmp/dummy/Gemfile +0 -50
- data/spec/integration/tmp/dummy/README.md +0 -24
- data/spec/integration/tmp/dummy/Rakefile +0 -6
- data/spec/integration/tmp/dummy/app/assets/config/manifest.js +0 -3
- data/spec/integration/tmp/dummy/app/assets/javascripts/application.js +0 -16
- data/spec/integration/tmp/dummy/app/assets/javascripts/cable.js +0 -13
- data/spec/integration/tmp/dummy/app/assets/stylesheets/application.css +0 -15
- data/spec/integration/tmp/dummy/app/channels/application_cable/channel.rb +0 -5
- data/spec/integration/tmp/dummy/app/channels/application_cable/connection.rb +0 -5
- data/spec/integration/tmp/dummy/app/controllers/application_controller.rb +0 -4
- data/spec/integration/tmp/dummy/app/controllers/graphql_controller.rb +0 -44
- data/spec/integration/tmp/dummy/app/helpers/application_helper.rb +0 -3
- data/spec/integration/tmp/dummy/app/jobs/application_job.rb +0 -3
- data/spec/integration/tmp/dummy/app/mailers/application_mailer.rb +0 -5
- data/spec/integration/tmp/dummy/app/mydirectory/dummy_schema.rb +0 -5
- data/spec/integration/tmp/dummy/app/mydirectory/mutations/update_name.rb +0 -15
- data/spec/integration/tmp/dummy/app/mydirectory/types/base_enum.rb +0 -5
- data/spec/integration/tmp/dummy/app/mydirectory/types/base_input_object.rb +0 -5
- data/spec/integration/tmp/dummy/app/mydirectory/types/base_interface.rb +0 -6
- data/spec/integration/tmp/dummy/app/mydirectory/types/base_object.rb +0 -5
- data/spec/integration/tmp/dummy/app/mydirectory/types/base_scalar.rb +0 -5
- data/spec/integration/tmp/dummy/app/mydirectory/types/base_union.rb +0 -5
- data/spec/integration/tmp/dummy/app/mydirectory/types/mutation_type.rb +0 -12
- data/spec/integration/tmp/dummy/app/mydirectory/types/query_type.rb +0 -14
- data/spec/integration/tmp/dummy/app/views/layouts/application.html.erb +0 -14
- data/spec/integration/tmp/dummy/app/views/layouts/mailer.html.erb +0 -13
- data/spec/integration/tmp/dummy/app/views/layouts/mailer.text.erb +0 -1
- data/spec/integration/tmp/dummy/bin/bundle +0 -3
- data/spec/integration/tmp/dummy/bin/rails +0 -4
- data/spec/integration/tmp/dummy/bin/rake +0 -4
- data/spec/integration/tmp/dummy/bin/setup +0 -34
- data/spec/integration/tmp/dummy/bin/update +0 -29
- data/spec/integration/tmp/dummy/config.ru +0 -5
- data/spec/integration/tmp/dummy/config/application.rb +0 -26
- data/spec/integration/tmp/dummy/config/boot.rb +0 -4
- data/spec/integration/tmp/dummy/config/cable.yml +0 -9
- data/spec/integration/tmp/dummy/config/environment.rb +0 -6
- data/spec/integration/tmp/dummy/config/environments/development.rb +0 -52
- data/spec/integration/tmp/dummy/config/environments/production.rb +0 -84
- data/spec/integration/tmp/dummy/config/environments/test.rb +0 -43
- data/spec/integration/tmp/dummy/config/initializers/application_controller_renderer.rb +0 -9
- data/spec/integration/tmp/dummy/config/initializers/assets.rb +0 -12
- data/spec/integration/tmp/dummy/config/initializers/backtrace_silencers.rb +0 -8
- data/spec/integration/tmp/dummy/config/initializers/cookies_serializer.rb +0 -6
- data/spec/integration/tmp/dummy/config/initializers/filter_parameter_logging.rb +0 -5
- data/spec/integration/tmp/dummy/config/initializers/inflections.rb +0 -17
- data/spec/integration/tmp/dummy/config/initializers/mime_types.rb +0 -5
- data/spec/integration/tmp/dummy/config/initializers/new_framework_defaults.rb +0 -24
- data/spec/integration/tmp/dummy/config/initializers/session_store.rb +0 -4
- data/spec/integration/tmp/dummy/config/initializers/wrap_parameters.rb +0 -10
- data/spec/integration/tmp/dummy/config/locales/en.yml +0 -23
- data/spec/integration/tmp/dummy/config/puma.rb +0 -48
- data/spec/integration/tmp/dummy/config/routes.rb +0 -9
- data/spec/integration/tmp/dummy/config/secrets.yml +0 -22
- data/spec/integration/tmp/dummy/db/seeds.rb +0 -8
- data/spec/integration/tmp/dummy/log/test.log +0 -0
- data/spec/integration/tmp/dummy/public/404.html +0 -67
- data/spec/integration/tmp/dummy/public/422.html +0 -67
- data/spec/integration/tmp/dummy/public/500.html +0 -66
- data/spec/integration/tmp/dummy/public/apple-touch-icon-precomposed.png +0 -0
- data/spec/integration/tmp/dummy/public/apple-touch-icon.png +0 -0
- data/spec/integration/tmp/dummy/public/favicon.ico +0 -0
- data/spec/integration/tmp/dummy/public/robots.txt +0 -5
- data/spec/integration/tmp/dummy/test/test_helper.rb +0 -8
@@ -24,6 +24,11 @@ module GraphQL
|
|
24
24
|
# @return [Class, Module, nil] If this argument should load an application object, this is the type of object to load
|
25
25
|
attr_reader :loads
|
26
26
|
|
27
|
+
# @return [Boolean] true if a resolver defined this argument
|
28
|
+
def from_resolver?
|
29
|
+
@from_resolver
|
30
|
+
end
|
31
|
+
|
27
32
|
# @param arg_name [Symbol]
|
28
33
|
# @param type_expr
|
29
34
|
# @param desc [String]
|
@@ -33,7 +38,9 @@ module GraphQL
|
|
33
38
|
# @param as [Symbol] Override the keyword name when passed to a method
|
34
39
|
# @param prepare [Symbol] A method to call to transform this argument's valuebefore sending it to field resolution
|
35
40
|
# @param camelize [Boolean] if true, the name will be camelized when building the schema
|
36
|
-
|
41
|
+
# @param from_resolver [Boolean] if true, a Resolver class defined this argument
|
42
|
+
# @param method_access [Boolean] If false, don't build method access on legacy {Query::Arguments} instances.
|
43
|
+
def initialize(arg_name = nil, type_expr = nil, desc = nil, required:, type: nil, name: nil, loads: nil, description: nil, ast_node: nil, default_value: NO_DEFAULT, as: nil, from_resolver: false, camelize: true, prepare: nil, method_access: true, owner:, &definition_block)
|
37
44
|
arg_name ||= name
|
38
45
|
name_str = camelize ? Member::BuildType.camelize(arg_name.to_s) : arg_name.to_s
|
39
46
|
@name = name_str.freeze
|
@@ -46,6 +53,9 @@ module GraphQL
|
|
46
53
|
@loads = loads
|
47
54
|
@keyword = as || Schema::Member::BuildType.underscore(@name).to_sym
|
48
55
|
@prepare = prepare
|
56
|
+
@ast_node = ast_node
|
57
|
+
@from_resolver = from_resolver
|
58
|
+
@method_access = method_access
|
49
59
|
|
50
60
|
if definition_block
|
51
61
|
if definition_block.arity == 1
|
@@ -94,6 +104,7 @@ module GraphQL
|
|
94
104
|
argument.description = @description
|
95
105
|
argument.metadata[:type_class] = self
|
96
106
|
argument.as = @as
|
107
|
+
argument.method_access = @method_access
|
97
108
|
if NO_DEFAULT != @default_value
|
98
109
|
argument.default_value = @default_value
|
99
110
|
end
|
@@ -232,6 +232,7 @@ module GraphQL
|
|
232
232
|
name: input_argument.name,
|
233
233
|
type: type_resolver.call(input_argument.type),
|
234
234
|
description: input_argument.description,
|
235
|
+
method_access: false,
|
235
236
|
**kwargs,
|
236
237
|
)
|
237
238
|
|
@@ -269,6 +270,7 @@ module GraphQL
|
|
269
270
|
name: directive_argument.name,
|
270
271
|
type: type_resolver.call(directive_argument.type),
|
271
272
|
description: directive_argument.description,
|
273
|
+
method_access: false,
|
272
274
|
**kwargs,
|
273
275
|
)
|
274
276
|
|
@@ -306,6 +308,7 @@ module GraphQL
|
|
306
308
|
name: argument.name,
|
307
309
|
description: argument.description,
|
308
310
|
type: type_resolver.call(argument.type),
|
311
|
+
method_access: false,
|
309
312
|
**kwargs,
|
310
313
|
)
|
311
314
|
|
data/lib/graphql/schema/field.rb
CHANGED
@@ -205,7 +205,7 @@ module GraphQL
|
|
205
205
|
|
206
206
|
# TODO: I think non-string/symbol hash keys are wrongly normalized (eg `1` will not work)
|
207
207
|
method_name = method || hash_key || @underscored_name
|
208
|
-
resolver_method ||= @underscored_name
|
208
|
+
resolver_method ||= @underscored_name.to_sym
|
209
209
|
|
210
210
|
@method_str = method_name.to_s
|
211
211
|
@method_sym = method_name.to_sym
|
@@ -418,13 +418,10 @@ module GraphQL
|
|
418
418
|
end
|
419
419
|
|
420
420
|
def authorized?(object, context)
|
421
|
-
|
421
|
+
if @resolver_class
|
422
|
+
# The resolver will check itself during `resolve()`
|
422
423
|
@resolver_class.authorized?(object, context)
|
423
424
|
else
|
424
|
-
true
|
425
|
-
end
|
426
|
-
|
427
|
-
if self_auth
|
428
425
|
# Faster than `.any?`
|
429
426
|
arguments.each_value do |arg|
|
430
427
|
if !arg.authorized?(object, context)
|
@@ -432,8 +429,6 @@ module GraphQL
|
|
432
429
|
end
|
433
430
|
end
|
434
431
|
true
|
435
|
-
else
|
436
|
-
false
|
437
432
|
end
|
438
433
|
end
|
439
434
|
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module GraphQL
|
2
|
+
class Schema
|
3
|
+
module FindInheritedValue
|
4
|
+
private
|
5
|
+
|
6
|
+
def find_inherited_value(method_name, default_value = nil)
|
7
|
+
if self.is_a?(Class)
|
8
|
+
superclass.respond_to?(method_name, true) ? superclass.send(method_name) : default_value
|
9
|
+
else
|
10
|
+
ancestors[1..-1].each do |ancestor|
|
11
|
+
if ancestor.respond_to?(method_name, true)
|
12
|
+
return ancestor.send(method_name)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
default_value
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -23,7 +23,7 @@ module GraphQL
|
|
23
23
|
ruby_kwargs_key = arg_defn.keyword
|
24
24
|
loads = arg_defn.loads
|
25
25
|
|
26
|
-
if @ruby_style_hash.key?(ruby_kwargs_key) && loads
|
26
|
+
if @ruby_style_hash.key?(ruby_kwargs_key) && loads && !arg_defn.from_resolver?
|
27
27
|
value = @ruby_style_hash[ruby_kwargs_key]
|
28
28
|
@ruby_style_hash[ruby_kwargs_key] = if arg_defn.type.list?
|
29
29
|
GraphQL::Execution::Lazy.all(value.map { |val| load_application_object(arg_defn, loads, val) })
|
@@ -99,8 +99,6 @@ module GraphQL
|
|
99
99
|
attr_accessor :arguments_class
|
100
100
|
|
101
101
|
def argument(*args, **kwargs, &block)
|
102
|
-
# Translate `loads:` to `as:` if needed`
|
103
|
-
*args, kwargs = argument_with_loads(*args, **kwargs, &block)
|
104
102
|
argument_defn = super(*args, **kwargs, &block)
|
105
103
|
# Add a method access
|
106
104
|
method_name = argument_defn.keyword
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "graphql/schema/find_inherited_value"
|
4
|
+
|
3
5
|
module GraphQL
|
4
6
|
class Schema
|
5
7
|
class Member
|
@@ -7,6 +9,8 @@ module GraphQL
|
|
7
9
|
# @api private
|
8
10
|
# @see Classes that extend this, eg {GraphQL::Schema::Object}
|
9
11
|
module BaseDSLMethods
|
12
|
+
include GraphQL::Schema::FindInheritedValue
|
13
|
+
|
10
14
|
# Call this with a new name to override the default name for this schema member; OR
|
11
15
|
# call it without an argument to get the name of this schema member
|
12
16
|
#
|
@@ -42,7 +46,7 @@ module GraphQL
|
|
42
46
|
if new_description
|
43
47
|
@description = new_description
|
44
48
|
else
|
45
|
-
@description ||
|
49
|
+
@description || find_inherited_value(:description)
|
46
50
|
end
|
47
51
|
end
|
48
52
|
|
@@ -51,7 +55,7 @@ module GraphQL
|
|
51
55
|
if !new_introspection.nil?
|
52
56
|
@introspection = new_introspection
|
53
57
|
else
|
54
|
-
@introspection ||
|
58
|
+
@introspection || find_inherited_value(:introspection, false)
|
55
59
|
end
|
56
60
|
end
|
57
61
|
|
@@ -76,7 +80,7 @@ module GraphQL
|
|
76
80
|
alias :unwrap :itself
|
77
81
|
|
78
82
|
def overridden_graphql_name
|
79
|
-
@graphql_name ||
|
83
|
+
@graphql_name || find_inherited_value(:overridden_graphql_name)
|
80
84
|
end
|
81
85
|
|
82
86
|
# Creates the default name for a schema member.
|
@@ -113,21 +117,6 @@ module GraphQL
|
|
113
117
|
true
|
114
118
|
end
|
115
119
|
end
|
116
|
-
|
117
|
-
private
|
118
|
-
|
119
|
-
def find_inherited_method(method_name, default_value)
|
120
|
-
if self.is_a?(Class)
|
121
|
-
superclass.respond_to?(method_name) ? superclass.public_send(method_name) : default_value
|
122
|
-
else
|
123
|
-
ancestors[1..-1].each do |ancestor|
|
124
|
-
if ancestor.respond_to?(method_name)
|
125
|
-
return ancestor.public_send(method_name)
|
126
|
-
end
|
127
|
-
end
|
128
|
-
default_value
|
129
|
-
end
|
130
|
-
end
|
131
120
|
end
|
132
121
|
end
|
133
122
|
end
|
@@ -13,7 +13,10 @@ module GraphQL
|
|
13
13
|
cls.include(ArgumentObjectLoader)
|
14
14
|
end
|
15
15
|
|
16
|
-
|
16
|
+
# @see {GraphQL::Schema::Argument#initialize} for parameters
|
17
|
+
# @return [GraphQL::Schema::Argument] An instance of {arguments_class}, created from `*args`
|
18
|
+
def argument(*args, **kwargs, &block)
|
19
|
+
kwargs[:owner] = self
|
17
20
|
loads = kwargs[:loads]
|
18
21
|
if loads
|
19
22
|
name = args[0]
|
@@ -32,14 +35,6 @@ module GraphQL
|
|
32
35
|
|
33
36
|
kwargs[:as] ||= inferred_arg_name
|
34
37
|
end
|
35
|
-
|
36
|
-
return [*args, **kwargs]
|
37
|
-
end
|
38
|
-
|
39
|
-
# @see {GraphQL::Schema::Argument#initialize} for parameters
|
40
|
-
# @return [GraphQL::Schema::Argument] An instance of {arguments_class}, created from `*args`
|
41
|
-
def argument(*args, **kwargs, &block)
|
42
|
-
kwargs[:owner] = self
|
43
38
|
arg_defn = self.argument_class.new(*args, **kwargs, &block)
|
44
39
|
add_argument(arg_defn)
|
45
40
|
end
|
@@ -38,10 +38,24 @@ module GraphQL
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
+
# A list of field names that we should advise users to pick a different
|
42
|
+
# resolve method name.
|
43
|
+
#
|
44
|
+
# @api private
|
45
|
+
CONFLICT_FIELD_NAMES = Set.new([
|
46
|
+
# GraphQL-Ruby conflicts
|
47
|
+
:context, :object,
|
48
|
+
# Ruby built-ins conflicts
|
49
|
+
:method, :class
|
50
|
+
])
|
51
|
+
|
41
52
|
# Register this field with the class, overriding a previous one if needed.
|
42
53
|
# @param field_defn [GraphQL::Schema::Field]
|
43
54
|
# @return [void]
|
44
55
|
def add_field(field_defn)
|
56
|
+
if CONFLICT_FIELD_NAMES.include?(field_defn.resolver_method)
|
57
|
+
warn "#{self.graphql_name}'s `field :#{field_defn.name}` conflicts with a built-in method, use `resolver_method:` to pick a different resolver method for this field (for example, `resolver_method: :resolve_#{field_defn.resolver_method}` and `def resolve_#{field_defn.resolver_method}`)"
|
58
|
+
end
|
45
59
|
own_fields[field_defn.name] = field_defn
|
46
60
|
nil
|
47
61
|
end
|
@@ -8,7 +8,7 @@ module GraphQL
|
|
8
8
|
if new_edge_type_class
|
9
9
|
@edge_type_class = new_edge_type_class
|
10
10
|
else
|
11
|
-
@edge_type_class ||
|
11
|
+
@edge_type_class || find_inherited_value(:edge_type_class, Types::Relay::BaseEdge)
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
@@ -16,7 +16,7 @@ module GraphQL
|
|
16
16
|
if new_connection_type_class
|
17
17
|
@connection_type_class = new_connection_type_class
|
18
18
|
else
|
19
|
-
@connection_type_class ||
|
19
|
+
@connection_type_class || find_inherited_value(:connection_type_class, Types::Relay::BaseConnection)
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
@@ -123,12 +123,36 @@ module GraphQL
|
|
123
123
|
# Called after arguments are loaded, but before resolving.
|
124
124
|
#
|
125
125
|
# Override it to check everything before calling the mutation.
|
126
|
-
# @param
|
126
|
+
# @param inputs [Hash] The input arguments
|
127
127
|
# @raise [GraphQL::ExecutionError] To add an error to the response
|
128
128
|
# @raise [GraphQL::UnauthorizedError] To signal an authorization failure
|
129
129
|
# @return [Boolean, early_return_data] If `false`, execution will stop (and `early_return_data` will be returned instead, if present.)
|
130
|
-
def authorized?(**
|
131
|
-
|
130
|
+
def authorized?(**inputs)
|
131
|
+
self.class.arguments.each_value do |argument|
|
132
|
+
arg_keyword = argument.keyword
|
133
|
+
if inputs.key?(arg_keyword) && !(value = inputs[arg_keyword]).nil? && (value != argument.default_value)
|
134
|
+
loads_type = @arguments_loads_as_type[arg_keyword]
|
135
|
+
# If this argument resulted in an object being loaded,
|
136
|
+
# then authorize this loaded object with its own policy.
|
137
|
+
#
|
138
|
+
# But if this argument was "just" a plain argument, like
|
139
|
+
# a boolean, then authorize it based on the mutation.
|
140
|
+
authorization_value = if loads_type
|
141
|
+
value
|
142
|
+
else
|
143
|
+
self
|
144
|
+
end
|
145
|
+
|
146
|
+
arg_auth, err = argument.authorized?(authorization_value, context)
|
147
|
+
if !arg_auth
|
148
|
+
return arg_auth, err
|
149
|
+
else
|
150
|
+
true
|
151
|
+
end
|
152
|
+
else
|
153
|
+
true
|
154
|
+
end
|
155
|
+
end
|
132
156
|
end
|
133
157
|
|
134
158
|
private
|
@@ -254,12 +278,11 @@ module GraphQL
|
|
254
278
|
# Add an argument to this field's signature, but
|
255
279
|
# also add some preparation hook methods which will be used for this argument
|
256
280
|
# @see {GraphQL::Schema::Argument#initialize} for the signature
|
257
|
-
def argument(
|
258
|
-
|
259
|
-
#
|
281
|
+
def argument(*args, **kwargs, &block)
|
282
|
+
loads = kwargs[:loads]
|
283
|
+
# Use `from_resolver: true` to short-circuit the InputObject's own `loads:` implementation
|
260
284
|
# so that we can support `#load_{x}` methods below.
|
261
|
-
|
262
|
-
arg_defn = super(*args, **kwargs)
|
285
|
+
arg_defn = super(*args, from_resolver: true, **kwargs)
|
263
286
|
own_arguments_loads_as_type[arg_defn.keyword] = loads if loads
|
264
287
|
|
265
288
|
if loads && arg_defn.type.list?
|
@@ -27,7 +27,7 @@ module GraphQL
|
|
27
27
|
if new_class
|
28
28
|
@field_class = new_class
|
29
29
|
else
|
30
|
-
@field_class ||
|
30
|
+
@field_class || find_inherited_value(:field_class, GraphQL::Schema::Field)
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
@@ -37,8 +37,9 @@ module GraphQL
|
|
37
37
|
def object_class(new_class = nil)
|
38
38
|
if new_class
|
39
39
|
@object_class = new_class
|
40
|
+
else
|
41
|
+
@object_class || find_inherited_value(:object_class, GraphQL::Schema::Object)
|
40
42
|
end
|
41
|
-
@object_class || (superclass.respond_to?(:object_class) ? superclass.object_class : GraphQL::Schema::Object)
|
42
43
|
end
|
43
44
|
|
44
45
|
private
|
@@ -17,7 +17,7 @@ module GraphQL
|
|
17
17
|
|
18
18
|
def assert_required_args(ast_node, defn)
|
19
19
|
present_argument_names = ast_node.arguments.map(&:name)
|
20
|
-
required_argument_names =
|
20
|
+
required_argument_names = context.warden.arguments(defn)
|
21
21
|
.select { |a| a.type.kind.non_null? }
|
22
22
|
.map(&:name)
|
23
23
|
|
data/lib/graphql/version.rb
CHANGED
@@ -31,6 +31,8 @@ describe GraphQL::Analysis do
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
+
let(:schema) { Class.new(Dummy::Schema) }
|
35
|
+
|
34
36
|
describe ".analyze_query" do
|
35
37
|
let(:node_counter) {
|
36
38
|
->(memo, visit_type, irep_node) {
|
@@ -43,7 +45,7 @@ describe GraphQL::Analysis do
|
|
43
45
|
let(:analyzers) { [type_collector, node_counter] }
|
44
46
|
let(:reduce_result) { GraphQL::Analysis.analyze_query(query, analyzers) }
|
45
47
|
let(:variables) { {} }
|
46
|
-
let(:query) { GraphQL::Query.new(
|
48
|
+
let(:query) { GraphQL::Query.new(schema, query_string, variables: variables) }
|
47
49
|
let(:query_string) {%|
|
48
50
|
{
|
49
51
|
cheese(id: 1) {
|
@@ -58,7 +60,7 @@ describe GraphQL::Analysis do
|
|
58
60
|
let(:analyzers) { [type_collector, conditional_analyzer] }
|
59
61
|
|
60
62
|
describe "when analyze? returns false" do
|
61
|
-
let(:query) { GraphQL::Query.new(
|
63
|
+
let(:query) { GraphQL::Query.new(schema, query_string, variables: variables, context: { analyze: false }) }
|
62
64
|
|
63
65
|
it "does not run the analyzer" do
|
64
66
|
# Only type_collector ran
|
@@ -67,7 +69,7 @@ describe GraphQL::Analysis do
|
|
67
69
|
end
|
68
70
|
|
69
71
|
describe "when analyze? returns true" do
|
70
|
-
let(:query) { GraphQL::Query.new(
|
72
|
+
let(:query) { GraphQL::Query.new(schema, query_string, variables: variables, context: { analyze: true }) }
|
71
73
|
|
72
74
|
it "it runs the analyzer" do
|
73
75
|
# Both analyzers ran
|
@@ -93,7 +95,7 @@ describe GraphQL::Analysis do
|
|
93
95
|
it "emits traces" do
|
94
96
|
traces = TestTracing.with_trace do
|
95
97
|
ctx = { tracers: [TestTracing] }
|
96
|
-
|
98
|
+
schema.execute(query_string, context: ctx)
|
97
99
|
end
|
98
100
|
|
99
101
|
# The query_trace is on the list _first_ because it finished first
|
@@ -119,14 +121,7 @@ describe GraphQL::Analysis do
|
|
119
121
|
let(:variable_accessor) { ->(memo, visit_type, irep_node) { query.variables["cheeseId"] } }
|
120
122
|
|
121
123
|
before do
|
122
|
-
|
123
|
-
Dummy::Schema.query_analyzers.clear
|
124
|
-
Dummy::Schema.query_analyzers << variable_accessor
|
125
|
-
end
|
126
|
-
|
127
|
-
after do
|
128
|
-
Dummy::Schema.query_analyzers.clear
|
129
|
-
Dummy::Schema.query_analyzers.push(*@previous_query_analyzers)
|
124
|
+
schema.query_analyzer(variable_accessor)
|
130
125
|
end
|
131
126
|
|
132
127
|
it "returns an error" do
|
@@ -213,7 +208,7 @@ describe GraphQL::Analysis do
|
|
213
208
|
let(:flavor_catcher) { FlavorCatcher.new }
|
214
209
|
let(:analyzers) { [id_catcher, flavor_catcher] }
|
215
210
|
let(:reduce_result) { GraphQL::Analysis.analyze_query(query, analyzers) }
|
216
|
-
let(:query) { GraphQL::Query.new(
|
211
|
+
let(:query) { GraphQL::Query.new(schema, query_string) }
|
217
212
|
let(:query_string) {%|
|
218
213
|
{
|
219
214
|
cheese(id: 1) {
|
@@ -222,7 +217,12 @@ describe GraphQL::Analysis do
|
|
222
217
|
}
|
223
218
|
}
|
224
219
|
|}
|
225
|
-
let(:schema)
|
220
|
+
let(:schema) do
|
221
|
+
schema = Class.new(Dummy::Schema)
|
222
|
+
schema.query_analyzer(id_catcher)
|
223
|
+
schema.query_analyzer(flavor_catcher)
|
224
|
+
schema
|
225
|
+
end
|
226
226
|
let(:result) { schema.execute(query_string) }
|
227
227
|
let(:query_string) {%|
|
228
228
|
{
|
@@ -233,17 +233,6 @@ describe GraphQL::Analysis do
|
|
233
233
|
}
|
234
234
|
|}
|
235
235
|
|
236
|
-
before do
|
237
|
-
@previous_query_analyzers = Dummy::Schema.query_analyzers.dup
|
238
|
-
Dummy::Schema.query_analyzers.clear
|
239
|
-
Dummy::Schema.query_analyzers << id_catcher << flavor_catcher
|
240
|
-
end
|
241
|
-
|
242
|
-
after do
|
243
|
-
Dummy::Schema.query_analyzers.clear
|
244
|
-
Dummy::Schema.query_analyzers.push(*@previous_query_analyzers)
|
245
|
-
end
|
246
|
-
|
247
236
|
it "groups all errors together" do
|
248
237
|
data = result["data"]
|
249
238
|
errors = result["errors"]
|