graphql 1.8.0.pre11 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/templates/schema.erb +1 -1
  3. data/lib/graphql/function.rb +2 -0
  4. data/lib/graphql/railtie.rb +1 -1
  5. data/lib/graphql/schema.rb +1 -0
  6. data/lib/graphql/schema/argument.rb +3 -2
  7. data/lib/graphql/schema/build_from_definition.rb +1 -1
  8. data/lib/graphql/schema/field.rb +96 -49
  9. data/lib/graphql/schema/interface.rb +21 -3
  10. data/lib/graphql/schema/list.rb +4 -0
  11. data/lib/graphql/schema/member/accepts_definition.rb +2 -2
  12. data/lib/graphql/schema/member/base_dsl_methods.rb +4 -0
  13. data/lib/graphql/schema/member/build_type.rb +4 -2
  14. data/lib/graphql/schema/member/has_fields.rb +1 -8
  15. data/lib/graphql/schema/mutation.rb +19 -88
  16. data/lib/graphql/schema/non_null.rb +4 -0
  17. data/lib/graphql/schema/object.rb +1 -1
  18. data/lib/graphql/schema/relay_classic_mutation.rb +14 -15
  19. data/lib/graphql/schema/resolver.rb +122 -0
  20. data/lib/graphql/subscriptions/instrumentation.rb +5 -1
  21. data/lib/graphql/subscriptions/serialize.rb +2 -0
  22. data/lib/graphql/tracing/new_relic_tracing.rb +26 -0
  23. data/lib/graphql/version.rb +1 -1
  24. data/readme.md +1 -1
  25. data/spec/generators/graphql/install_generator_spec.rb +1 -1
  26. data/spec/graphql/relay/mutation_spec.rb +5 -3
  27. data/spec/graphql/schema/build_from_definition_spec.rb +1 -1
  28. data/spec/graphql/schema/field_spec.rb +7 -24
  29. data/spec/graphql/schema/interface_spec.rb +25 -0
  30. data/spec/graphql/schema/member/accepts_definition_spec.rb +22 -0
  31. data/spec/graphql/schema/member/build_type_spec.rb +17 -0
  32. data/spec/graphql/schema/mutation_spec.rb +15 -14
  33. data/spec/graphql/schema/resolver_spec.rb +131 -0
  34. data/spec/graphql/subscriptions_spec.rb +267 -205
  35. data/spec/graphql/tracing/new_relic_tracing_spec.rb +47 -0
  36. data/spec/support/jazz.rb +6 -1
  37. data/spec/support/new_relic.rb +24 -0
  38. data/spec/support/star_trek/schema.rb +2 -2
  39. data/spec/support/star_wars/schema.rb +1 -2
  40. metadata +13 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f9824961c7be659d7f815105dce1ed73cb0524b8
4
- data.tar.gz: '08b3edfb6cc0fa00917cae9faf8c6c166e1cd2a8'
3
+ metadata.gz: f5283bf51e22ac60f8d9368d9cc19b8c6d038d8b
4
+ data.tar.gz: 147ec429661a6fbc1aaef685ba94c8a81d87910e
5
5
  SHA512:
6
- metadata.gz: 69707f9127dddff3f1039b066db1a46f1c2bd8a3b9527d4d73bd109734026da47623eb602a9988c300edef8ddf978ddc12fab355248895fcab6d37397ed7b00b
7
- data.tar.gz: 958bb3dd36b858af4273df812cdec568e463e9719efea31b1ba5249fce424259097d80c40ef70ffed61971e27b4d956287c26d82a9274a2e7df34b106fc9e6fe
6
+ metadata.gz: 06a2a8730fc1c13dc0a0d76a35b19e89dd40ad842e41618abb1b05a7f75b667eede56c106728e3e68bd531e36e29b28050b991319599b7952ac3285fb3f9be3c
7
+ data.tar.gz: 8231c7696681477decf92b0665f3e4249b308153338c8d7cf5102b7e95133b9ac7aa6156f3dddc026c4178ea9fcb25d7f181f752298d5cf38185141af653a471
@@ -21,7 +21,7 @@
21
21
  }
22
22
 
23
23
  # Object Resolution
24
- resolve_type -> (obj, ctx) {
24
+ resolve_type -> (type, obj, ctx) {
25
25
  # TODO: Implement this function
26
26
  # to return the correct type for `obj`
27
27
  raise(NotImplementedError)
@@ -28,6 +28,8 @@ module GraphQL
28
28
  # field :post, function: FindRecord.new(model: Post, type: PostType)
29
29
  # field :comment, function: FindRecord.new(model: Comment, type: CommentType)
30
30
  # end
31
+ #
32
+ # @see {GraphQL::Schema::Resolver} for a replacement for `GraphQL::Function`
31
33
  class Function
32
34
  # @return [Hash<String => GraphQL::Argument>] Arguments, keyed by name
33
35
  def arguments
@@ -72,7 +72,7 @@ module GraphQL
72
72
  unless File.exists?(destination_file)
73
73
  FileUtils.mkdir_p(File.dirname(destination_file))
74
74
  File.open(destination_file, 'w') do |f|
75
- f.write "class Types::BaseInterface < GraphQL::Schema::Interface\nend"
75
+ f.write "module Types::BaseInterface\n include GraphQL::Schema::Interface\nend"
76
76
  end
77
77
  end
78
78
 
@@ -29,6 +29,7 @@ require "graphql/schema/enum"
29
29
  require "graphql/schema/field"
30
30
  require "graphql/schema/input_object"
31
31
  require "graphql/schema/interface"
32
+ require "graphql/schema/resolver"
32
33
  require "graphql/schema/mutation"
33
34
  require "graphql/schema/relay_classic_mutation"
34
35
  require "graphql/schema/object"
@@ -28,9 +28,10 @@ module GraphQL
28
28
  # @param as [Symbol] Override the keyword name when passed to a method
29
29
  # @param prepare [Symbol] A method to call to tranform this argument's valuebefore sending it to field resolution
30
30
  # @param camelize [Boolean] if true, the name will be camelized when building the schema
31
- def initialize(arg_name, type_expr, desc = nil, required:, description: nil, default_value: NO_DEFAULT, as: nil, camelize: true, prepare: nil, owner:, &definition_block)
31
+ def initialize(arg_name = nil, type_expr = nil, desc = nil, required:, type: nil, name: nil, description: nil, default_value: NO_DEFAULT, as: nil, camelize: true, prepare: nil, owner:, &definition_block)
32
+ arg_name ||= name
32
33
  @name = camelize ? Member::BuildType.camelize(arg_name.to_s) : arg_name.to_s
33
- @type_expr = type_expr
34
+ @type_expr = type_expr || type
34
35
  @description = desc || description
35
36
  @null = !required
36
37
  @default_value = default_value
@@ -237,7 +237,7 @@ module GraphQL
237
237
  **kwargs,
238
238
  )
239
239
 
240
- argument.ast_node = input_object_type_definition
240
+ argument.ast_node = input_argument
241
241
 
242
242
  [
243
243
  input_argument.name,
@@ -8,7 +8,7 @@ module GraphQL
8
8
  include GraphQL::Schema::Member::HasArguments
9
9
 
10
10
  # @return [String] the GraphQL name for this field, camelized unless `camelize: false` is provided
11
- attr_reader :name
11
+ attr_accessor :name
12
12
 
13
13
  # @return [String]
14
14
  attr_accessor :description
@@ -22,9 +22,55 @@ module GraphQL
22
22
  # @return [Class] The type that this field belongs to
23
23
  attr_reader :owner
24
24
 
25
- # @return [Class, nil] The mutation this field was derived from, if there is one
26
- def mutation
27
- @mutation || @mutation_class
25
+
26
+ # @return [Class, nil] The {Schema::Resolver} this field was derived from, if there is one
27
+ def resolver
28
+ @resolver_class
29
+ end
30
+
31
+ alias :mutation :resolver
32
+
33
+ # Create a field instance from a list of arguments, keyword arguments, and a block.
34
+ #
35
+ # This method implements prioritization between the `resolver` or `mutation` defaults
36
+ # and the local overrides via other keywords.
37
+ #
38
+ # It also normalizes positional arguments into keywords for {Schema::Field#initialize}.
39
+ # @param resolver [Class] A {GraphQL::Schema::Resolver} class to use for field configuration
40
+ # @param mutation [Class] A {GraphQL::Schema::Mutation} class to use for field configuration
41
+ # @return [GraphQL::Schema:Field] an instance of `self
42
+ # @see {.initialize} for other options
43
+ def self.from_options(name = nil, type = nil, desc = nil, resolver: nil, mutation: nil, **kwargs, &block)
44
+ if (parent_config = resolver || mutation)
45
+ # Get the parent config, merge in local overrides
46
+ kwargs = parent_config.field_options.merge(kwargs)
47
+ # Add a reference to that parent class
48
+ kwargs[:resolver_class] = parent_config
49
+ end
50
+
51
+ if name
52
+ kwargs[:name] = name
53
+ end
54
+
55
+ if !type.nil?
56
+ if type.is_a?(GraphQL::Field)
57
+ raise ArgumentError, "A GraphQL::Field was passed as the second argument, use the `field:` keyword for this instead."
58
+ end
59
+ if desc
60
+ if kwargs[:description]
61
+ raise ArgumentError, "Provide description as a positional argument or `description:` keyword, but not both (#{desc.inspect}, #{kwargs[:description].inspect})"
62
+ end
63
+
64
+ kwargs[:description] = desc
65
+ kwargs[:type] = type
66
+ elsif (kwargs[:field] || kwargs[:function] || resolver || mutation) && type.is_a?(String)
67
+ # The return type should be copied from `field` or `function`, and the second positional argument is the description
68
+ kwargs[:description] = type
69
+ else
70
+ kwargs[:type] = type
71
+ end
72
+ end
73
+ new(**kwargs, &block)
28
74
  end
29
75
 
30
76
  # @param name [Symbol] The underscore-cased version of this field name (will be camelized for the GraphQL API)
@@ -42,39 +88,29 @@ module GraphQL
42
88
  # @param resolve [<#call(obj, args, ctx)>] **deprecated** for compatibility with <1.8.0
43
89
  # @param field [GraphQL::Field, GraphQL::Schema::Field] **deprecated** for compatibility with <1.8.0
44
90
  # @param function [GraphQL::Function] **deprecated** for compatibility with <1.8.0
45
- # @param mutation [Class] A {Schema::Mutation} class for serving this field
46
- # @param mutation_class [Class] (Private) A {Schema::Mutation} which this field was derived from.
47
- # @param arguments [{String=>GraphQL::Schema::Arguments}] Arguments for this field (may be added in the block, also)
91
+ # @param resolver_class [Class] (Private) A {Schema::Resolver} which this field was derived from. Use `resolver:` to create a field with a resolver.
92
+ # @param arguments [{String=>GraphQL::Schema::Argument, Hash}] Arguments for this field (may be added in the block, also)
48
93
  # @param camelize [Boolean] If true, the field name will be camelized when building the schema
49
94
  # @param complexity [Numeric] When provided, set the complexity for this field
50
- def initialize(name, return_type_expr = nil, desc = nil, owner: nil, null: nil, field: nil, function: nil, description: nil, deprecation_reason: nil, method: nil, connection: nil, max_page_size: nil, resolve: nil, introspection: false, hash_key: nil, camelize: true, complexity: 1, extras: [], mutation: nil, mutation_class: nil, arguments: {}, &definition_block)
51
- if (field || function) && desc.nil? && return_type_expr.is_a?(String)
52
- # The return type should be copied from `field` or `function`, and the second positional argument is the description
53
- desc = return_type_expr
54
- return_type_expr = nil
55
- end
56
- if mutation && (return_type_expr || desc || description || function || field || !null.nil? || deprecation_reason || method || resolve || introspection || hash_key)
57
- raise ArgumentError, "when keyword `mutation:` is present, all arguments are ignored, please remove them"
95
+ # @param subscription_scope [Symbol, String] A key in `context` which will be used to scope subscription payloads
96
+ def initialize(type: nil, name: nil, owner: nil, null: nil, field: nil, function: nil, description: nil, deprecation_reason: nil, method: nil, connection: nil, max_page_size: nil, resolve: nil, introspection: false, hash_key: nil, camelize: true, complexity: 1, extras: [], resolver_class: nil, subscription_scope: nil, arguments: {}, &definition_block)
97
+
98
+ if name.nil?
99
+ raise ArgumentError, "missing first `name` argument or keyword `name:`"
58
100
  end
59
- if !(field || function || mutation)
60
- if return_type_expr.nil?
61
- raise ArgumentError, "missing positional argument `type`"
101
+ if !(field || function || mutation || resolver)
102
+ if type.nil?
103
+ raise ArgumentError, "missing second `type` argument or keyword `type:`"
62
104
  end
63
105
  if null.nil?
64
106
  raise ArgumentError, "missing keyword argument null:"
65
107
  end
66
108
  end
67
- if (field || function || resolve || resolve) && extras.any?
109
+ if (field || function || resolve || mutation) && extras.any?
68
110
  raise ArgumentError, "keyword `extras:` may only be used with method-based resolve, please remove `field:`, `function:`, `resolve:`, or `mutation:`"
69
111
  end
70
- if return_type_expr.is_a?(GraphQL::Field)
71
- raise ArgumentError, "A GraphQL::Field was passed as the second argument, use the `field:` keyword for this instead."
72
- end
73
112
  @name = camelize ? Member::BuildType.camelize(name.to_s) : name.to_s
74
- if description && desc
75
- raise ArgumentError, "Provide description as a positional argument or `description:` keyword, but not both (#{desc.inspect}, #{description.inspect})"
76
- end
77
- @description = description || desc
113
+ @description = description
78
114
  if field.is_a?(GraphQL::Schema::Field)
79
115
  @field_instance = field
80
116
  else
@@ -93,17 +129,26 @@ module GraphQL
93
129
  @method_str = method_name.to_s
94
130
  @method_sym = method_name.to_sym
95
131
  @complexity = complexity
96
- @return_type_expr = return_type_expr
132
+ @return_type_expr = type
97
133
  @return_type_null = null
98
134
  @connection = connection
99
135
  @max_page_size = max_page_size
100
136
  @introspection = introspection
101
137
  @extras = extras
102
- @mutation = mutation
103
- @mutation_class = mutation_class
138
+ @resolver_class = resolver_class
139
+
104
140
  # Override the default from HasArguments
105
- @own_arguments = arguments
141
+ @own_arguments = {}
142
+ arguments.each do |name, arg|
143
+ if arg.is_a?(Hash)
144
+ argument(name: name, **arg)
145
+ else
146
+ @own_arguments[name] = arg
147
+ end
148
+ end
149
+
106
150
  @owner = owner
151
+ @subscription_scope = subscription_scope
107
152
 
108
153
  if definition_block
109
154
  instance_eval(&definition_block)
@@ -142,9 +187,6 @@ module GraphQL
142
187
  # this field was previously defined and passed here, so delegate to it
143
188
  if @field_instance
144
189
  return @field_instance.to_graphql
145
- elsif @mutation
146
- field_inst = @mutation.graphql_field
147
- return field_inst.to_graphql
148
190
  end
149
191
 
150
192
 
@@ -181,8 +223,11 @@ module GraphQL
181
223
  field_defn.deprecation_reason = @deprecation_reason
182
224
  end
183
225
 
184
- if @mutation_class
185
- field_defn.mutation = @mutation_class
226
+ if @resolver_class
227
+ if @resolver_class < GraphQL::Schema::Mutation
228
+ field_defn.mutation = @resolver_class
229
+ end
230
+ field_defn.metadata[:resolver] = @resolver_class
186
231
  end
187
232
 
188
233
  field_defn.resolve = self.method(:resolve_field)
@@ -190,6 +235,7 @@ module GraphQL
190
235
  field_defn.connection_max_page_size = @max_page_size
191
236
  field_defn.introspection = @introspection
192
237
  field_defn.complexity = @complexity
238
+ field_defn.subscription_scope = @subscription_scope
193
239
 
194
240
  # apply this first, so it can be overriden below
195
241
  if @connection
@@ -207,6 +253,15 @@ module GraphQL
207
253
  field_defn.arguments[arg_graphql.name] = arg_graphql
208
254
  end
209
255
 
256
+ # Support a passed-in proc, one way or another
257
+ @resolve_proc = if @resolve
258
+ @resolve
259
+ elsif @function
260
+ @function
261
+ elsif @field
262
+ @field.resolve_proc
263
+ end
264
+
210
265
  # Ok, `self` isn't a class, but this is for consistency with the classes
211
266
  field_defn.metadata[:type_class] = self
212
267
 
@@ -223,22 +278,14 @@ module GraphQL
223
278
  #
224
279
  # Eventually, we might hook up field instances to execution in another way. TBD.
225
280
  def resolve_field(obj, args, ctx)
226
- if @resolve || @function || @field
227
- # Support a passed-in proc, one way or another
228
- prev_resolve = if @resolve
229
- @resolve
230
- elsif @function
231
- @function
232
- elsif @field
233
- @field.resolve_proc
234
- end
235
-
281
+ if @resolve_proc
236
282
  # Might be nil, still want to call the func in that case
237
283
  inner_obj = obj && obj.object
238
- prev_resolve.call(inner_obj, args, ctx)
239
- elsif @mutation_class
240
- mutation_inst = @mutation_class.new(object: obj, arguments: args, context: ctx.query.context)
241
- public_send_field(mutation_inst, args, ctx)
284
+ @resolve_proc.call(inner_obj, args, ctx)
285
+ elsif @resolver_class
286
+ inner_obj = obj && obj.object
287
+ singleton_inst = @resolver_class.new(object: inner_obj, context: ctx.query.context)
288
+ public_send_field(singleton_inst, args, ctx)
242
289
  else
243
290
  public_send_field(obj, args, ctx)
244
291
  end
@@ -22,12 +22,22 @@ module GraphQL
22
22
  if !child_class.is_a?(Class)
23
23
  # In this case, it's been included into another interface.
24
24
  # This is how interface inheritance is implemented
25
- child_class.const_set(:DefinitionMethods, Module.new)
26
- child_class.extend(child_class::DefinitionMethods)
25
+
26
+ # Use an instance variable to tell whether it's been included previously or not;
27
+ # You can't use constant detection because constants are brought into scope
28
+ # by `include`, which has already happened at this point.
29
+ if !child_class.instance_variable_defined?(:@_definition_methods)
30
+ defn_methods_module = Module.new
31
+ child_class.instance_variable_set(:@_definition_methods, defn_methods_module)
32
+ child_class.const_set(:DefinitionMethods, defn_methods_module)
33
+ child_class.extend(child_class::DefinitionMethods)
34
+ end
35
+
27
36
  # We need this before we can call `own_interfaces`
28
37
  child_class.extend(Schema::Interface::DefinitionMethods)
38
+
29
39
  child_class.own_interfaces << self
30
- child_class.own_interfaces.each do |interface_defn|
40
+ child_class.interfaces.each do |interface_defn|
31
41
  child_class.extend(interface_defn::DefinitionMethods)
32
42
  end
33
43
  elsif child_class < GraphQL::Schema::Object
@@ -76,12 +86,20 @@ module GraphQL
76
86
  def own_interfaces
77
87
  @own_interfaces ||= []
78
88
  end
89
+
90
+ def interfaces
91
+ own_interfaces + (own_interfaces.map { |i| i.own_interfaces }).flatten
92
+ end
79
93
  end
80
94
 
81
95
  # Extend this _after_ `DefinitionMethods` is defined, so it will be used
82
96
  extend GraphQL::Schema::Member::AcceptsDefinition
83
97
 
84
98
  extend DefinitionMethods
99
+
100
+ def unwrap
101
+ self
102
+ end
85
103
  end
86
104
  end
87
105
  end
@@ -23,6 +23,10 @@ module GraphQL
23
23
  def kind
24
24
  GraphQL::TypeKinds::LIST
25
25
  end
26
+
27
+ def unwrap
28
+ @of_type.unwrap
29
+ end
26
30
  end
27
31
  end
28
32
  end
@@ -69,7 +69,7 @@ module GraphQL
69
69
  if args.any?
70
70
  instance_variable_set(ivar_name, args)
71
71
  end
72
- instance_variable_get(ivar_name)
72
+ instance_variable_get(ivar_name) || (superclass.respond_to?(name) ? superclass.public_send(name) : nil)
73
73
  end
74
74
 
75
75
  define_method(name) do |*args|
@@ -86,7 +86,7 @@ module GraphQL
86
86
  if args.any?
87
87
  instance_variable_set(ivar_name, args)
88
88
  end
89
- instance_variable_get(ivar_name)
89
+ instance_variable_get(ivar_name) || ((int = interfaces.first { |i| i.respond_to?()}) && int.public_send(name))
90
90
  end
91
91
  end
92
92
  end
@@ -76,6 +76,10 @@ module GraphQL
76
76
  @graphql_name || find_inherited_method(:overridden_graphql_name, nil)
77
77
  end
78
78
 
79
+ def unwrap
80
+ self
81
+ end
82
+
79
83
  private
80
84
 
81
85
  def find_inherited_method(method_name, default_value)
@@ -101,13 +101,15 @@ module GraphQL
101
101
  when Array
102
102
  to_type_name(something.first)
103
103
  when Module
104
- if something < GraphQL::Schema::Member
104
+ if something.respond_to?(:graphql_name)
105
105
  something.graphql_name
106
106
  else
107
- something.name.split("::").last
107
+ to_type_name(something.name)
108
108
  end
109
109
  when String
110
110
  something.gsub(/\]\[\!/, "").split("::").last
111
+ when GraphQL::Schema::NonNull, GraphQL::Schema::List
112
+ to_type_name(something.unwrap)
111
113
  else
112
114
  raise "Unhandled to_type_name input: #{something} (#{something.class})"
113
115
  end
@@ -49,7 +49,7 @@ module GraphQL
49
49
  # @see {GraphQL::Schema::Field#initialize} for method signature
50
50
  # @return [void]
51
51
  def field(*args, **kwargs, &block)
52
- field_defn = build_field(*args, **kwargs, &block)
52
+ field_defn = field_class.from_options(*args, owner: self, **kwargs, &block)
53
53
  add_field(field_defn)
54
54
  nil
55
55
  end
@@ -103,13 +103,6 @@ module GraphQL
103
103
  end
104
104
 
105
105
  private
106
-
107
- # Initialize a field with this class's field class, but don't attach it.
108
- def build_field(*args, **kwargs, &block)
109
- kwargs[:owner] = self
110
- field_class.new(*args, **kwargs, &block)
111
- end
112
-
113
106
  # Find the magic module for holding super methods,
114
107
  # and add a field named `method_name` for implementing the field
115
108
  # called `field_name`.
@@ -58,51 +58,16 @@ module GraphQL
58
58
  # }
59
59
  # GRAPHQL
60
60
  #
61
- class Mutation < GraphQL::Schema::Member
61
+ class Mutation < GraphQL::Schema::Resolver
62
62
  extend GraphQL::Schema::Member::HasFields
63
- extend GraphQL::Schema::Member::HasArguments
64
-
65
- # @param object [Object] the initialize object, pass to {Query.initialize} as `root_value`
66
- # @param context [GraphQL::Query::Context]
67
- def initialize(object:, context:, arguments:)
68
- @object = object
69
- @context = context
70
- end
71
-
72
- # @return [Object] the root value of the operation
73
- attr_reader :object
74
-
75
- # @return [GraphQL::Query::Context]
76
- attr_reader :context
77
-
78
- # Do the work. Everything happens here.
79
- # @return [Hash] A key for each field in the return type
80
- # @return [Object] An object corresponding to the return type
81
- def resolve(**args)
82
- raise NotImplementedError, "#{self.class.name}#resolve should execute side effects and return a Symbol-keyed hash"
83
- end
84
-
85
- # This is a hook for classes to intercept resolution.
86
- # @see RelayClassicMutation for usage
87
- def resolve_mutation(args)
88
- resolve(args)
89
- end
90
63
 
91
64
  class << self
92
- def inherited(base)
93
- base.null(null)
94
- super
95
- end
96
-
97
- # Override the method from HasFields to support `field: Mutation.field`, for backwards compat.
98
- #
99
- # If called without any arguments, returns a `GraphQL::Field`.
100
- # @see {GraphQL::Schema::Member::HasFields.field} for default behavior
65
+ # Override this method to handle legacy-style usages of `MyMutation.field`
101
66
  def field(*args, &block)
102
- if args.none? && !block_given?
103
- graphql_field.graphql_definition
67
+ if args.none?
68
+ raise ArgumentError, "#{name}.field is used for adding fields to this mutation. Use `mutation: #{name}` to attach this mutation instead."
104
69
  else
105
- super(*args, &block)
70
+ super
106
71
  end
107
72
  end
108
73
 
@@ -118,20 +83,8 @@ module GraphQL
118
83
  @payload_type ||= generate_payload_type
119
84
  end
120
85
 
121
- # @return [GraphQL::Schema::Field] The generated field instance for this mutation
122
- # @see {GraphQL::Schema::Field}'s `mutation:` option, don't call this directly
123
- def graphql_field
124
- @graphql_field ||= generate_field
125
- end
126
-
127
- # @param new_name [String, nil] if present, override the class name to set this value
128
- # @return [String] The name of this mutation in the GraphQL schema (used for naming derived types and fields)
129
- def graphql_name(new_name = nil)
130
- if new_name
131
- @graphql_name = new_name
132
- end
133
- @graphql_name ||= self.name.split("::").last
134
- end
86
+ alias :type :payload_type
87
+ alias :type_expr :payload_type
135
88
 
136
89
  # An object class to use for deriving payload types
137
90
  # @param new_class [Class, nil] Defaults to {GraphQL::Schema::Object}
@@ -143,23 +96,22 @@ module GraphQL
143
96
  @object_class || (superclass.respond_to?(:object_class) ? superclass.object_class : GraphQL::Schema::Object)
144
97
  end
145
98
 
146
- # Additional info injected into {#resolve}
147
- # @see {GraphQL::Schema::Field#extras}
148
- def extras(new_extras = nil)
149
- if new_extras
150
- @extras = new_extras
99
+ def field_class(new_class = nil)
100
+ if new_class
101
+ @field_class = new_class
102
+ else
103
+ @field_class || find_inherited_method(:field_class, GraphQL::Schema::Field)
151
104
  end
152
- @extras || []
153
105
  end
154
106
 
155
- # Specifies whether or not the mutation is nullable. Defaults to `true`
156
- # @param allow_null [Boolean] Whether or not the response can be null
157
- def null(allow_null = nil)
158
- unless allow_null.nil?
159
- @null = allow_null
107
+ # An object class to use for deriving return types
108
+ # @param new_class [Class, nil] Defaults to {GraphQL::Schema::Object}
109
+ # @return [Class]
110
+ def object_class(new_class = nil)
111
+ if new_class
112
+ @object_class = new_class
160
113
  end
161
-
162
- @null.nil? ? true : @null
114
+ @object_class || (superclass.respond_to?(:object_class) ? superclass.object_class : GraphQL::Schema::Object)
163
115
  end
164
116
 
165
117
  private
@@ -180,27 +132,6 @@ module GraphQL
180
132
  end
181
133
  end
182
134
  end
183
-
184
- # This name will be used for the {.graphql_field}.
185
- def field_name
186
- graphql_name.sub(/^[A-Z]/, &:downcase)
187
- end
188
-
189
- # Build an instance of {.field_class} which will be used to execute this mutation.
190
- # To customize field generation, override this method.
191
- def generate_field
192
- # TODO support deprecation_reason
193
- self.field_class.new(
194
- field_name,
195
- payload_type,
196
- description,
197
- extras: extras,
198
- method: :resolve_mutation,
199
- mutation_class: self,
200
- arguments: arguments,
201
- null: null,
202
- )
203
- end
204
135
  end
205
136
  end
206
137
  end