graphql 1.13.17 → 2.0.20

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.

Potentially problematic release.


This version of graphql might be problematic. Click here for more details.

Files changed (260) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/install_generator.rb +1 -1
  3. data/lib/generators/graphql/relay.rb +3 -17
  4. data/lib/generators/graphql/templates/schema.erb +3 -0
  5. data/lib/graphql/analysis/ast/field_usage.rb +3 -1
  6. data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -1
  7. data/lib/graphql/analysis/ast/query_complexity.rb +1 -1
  8. data/lib/graphql/analysis/ast/query_depth.rb +0 -1
  9. data/lib/graphql/analysis/ast/visitor.rb +43 -36
  10. data/lib/graphql/analysis/ast.rb +2 -12
  11. data/lib/graphql/analysis.rb +0 -7
  12. data/lib/graphql/backtrace/table.rb +2 -20
  13. data/lib/graphql/backtrace/tracer.rb +2 -3
  14. data/lib/graphql/backtrace.rb +2 -8
  15. data/lib/graphql/dataloader/null_dataloader.rb +3 -1
  16. data/lib/graphql/dataloader/source.rb +9 -0
  17. data/lib/graphql/dataloader.rb +4 -1
  18. data/lib/graphql/dig.rb +1 -1
  19. data/lib/graphql/execution/errors.rb +12 -82
  20. data/lib/graphql/execution/interpreter/resolve.rb +26 -0
  21. data/lib/graphql/execution/interpreter/runtime.rb +159 -120
  22. data/lib/graphql/execution/interpreter.rb +187 -78
  23. data/lib/graphql/execution/lazy.rb +7 -21
  24. data/lib/graphql/execution/lookahead.rb +44 -40
  25. data/lib/graphql/execution/multiplex.rb +3 -174
  26. data/lib/graphql/execution.rb +11 -4
  27. data/lib/graphql/introspection/directive_type.rb +2 -2
  28. data/lib/graphql/introspection/dynamic_fields.rb +3 -8
  29. data/lib/graphql/introspection/entry_points.rb +2 -15
  30. data/lib/graphql/introspection/field_type.rb +1 -1
  31. data/lib/graphql/introspection/schema_type.rb +2 -2
  32. data/lib/graphql/introspection/type_type.rb +13 -6
  33. data/lib/graphql/introspection.rb +4 -3
  34. data/lib/graphql/language/document_from_schema_definition.rb +18 -35
  35. data/lib/graphql/language/lexer.rb +216 -1488
  36. data/lib/graphql/language/nodes.rb +65 -39
  37. data/lib/graphql/language/parser.rb +376 -364
  38. data/lib/graphql/language/parser.y +49 -44
  39. data/lib/graphql/language/printer.rb +37 -21
  40. data/lib/graphql/language/visitor.rb +191 -83
  41. data/lib/graphql/pagination/active_record_relation_connection.rb +0 -8
  42. data/lib/graphql/pagination/array_connection.rb +4 -2
  43. data/lib/graphql/pagination/connection.rb +31 -4
  44. data/lib/graphql/pagination/connections.rb +3 -28
  45. data/lib/graphql/pagination/relation_connection.rb +2 -0
  46. data/lib/graphql/query/context.rb +155 -196
  47. data/lib/graphql/query/input_validation_result.rb +1 -1
  48. data/lib/graphql/query/null_context.rb +0 -3
  49. data/lib/graphql/query/validation_pipeline.rb +10 -34
  50. data/lib/graphql/query/variables.rb +7 -20
  51. data/lib/graphql/query.rb +32 -42
  52. data/lib/graphql/railtie.rb +0 -104
  53. data/lib/graphql/rake_task/validate.rb +1 -1
  54. data/lib/graphql/rake_task.rb +29 -1
  55. data/lib/graphql/relay/range_add.rb +9 -20
  56. data/lib/graphql/relay.rb +0 -15
  57. data/lib/graphql/schema/addition.rb +7 -9
  58. data/lib/graphql/schema/argument.rb +36 -43
  59. data/lib/graphql/schema/build_from_definition.rb +32 -18
  60. data/lib/graphql/schema/directive/one_of.rb +12 -0
  61. data/lib/graphql/schema/directive/transform.rb +1 -1
  62. data/lib/graphql/schema/directive.rb +12 -23
  63. data/lib/graphql/schema/enum.rb +28 -39
  64. data/lib/graphql/schema/enum_value.rb +5 -25
  65. data/lib/graphql/schema/field/connection_extension.rb +4 -0
  66. data/lib/graphql/schema/field.rb +237 -339
  67. data/lib/graphql/schema/input_object.rb +56 -67
  68. data/lib/graphql/schema/interface.rb +0 -35
  69. data/lib/graphql/schema/introspection_system.rb +3 -8
  70. data/lib/graphql/schema/late_bound_type.rb +8 -2
  71. data/lib/graphql/schema/list.rb +0 -6
  72. data/lib/graphql/schema/loader.rb +1 -2
  73. data/lib/graphql/schema/member/base_dsl_methods.rb +17 -19
  74. data/lib/graphql/schema/member/build_type.rb +5 -7
  75. data/lib/graphql/schema/member/has_arguments.rb +146 -55
  76. data/lib/graphql/schema/member/has_ast_node.rb +12 -0
  77. data/lib/graphql/schema/member/has_deprecation_reason.rb +3 -4
  78. data/lib/graphql/schema/member/has_directives.rb +81 -59
  79. data/lib/graphql/schema/member/has_fields.rb +17 -4
  80. data/lib/graphql/schema/member/has_interfaces.rb +49 -10
  81. data/lib/graphql/schema/member/has_validators.rb +31 -5
  82. data/lib/graphql/schema/member/relay_shortcuts.rb +47 -2
  83. data/lib/graphql/schema/member/type_system_helpers.rb +17 -0
  84. data/lib/graphql/schema/member/validates_input.rb +1 -1
  85. data/lib/graphql/schema/member.rb +0 -6
  86. data/lib/graphql/schema/mutation.rb +0 -9
  87. data/lib/graphql/schema/non_null.rb +1 -7
  88. data/lib/graphql/schema/object.rb +15 -52
  89. data/lib/graphql/schema/relay_classic_mutation.rb +53 -42
  90. data/lib/graphql/schema/resolver/has_payload_type.rb +20 -10
  91. data/lib/graphql/schema/resolver.rb +41 -42
  92. data/lib/graphql/schema/scalar.rb +7 -22
  93. data/lib/graphql/schema/subscription.rb +0 -7
  94. data/lib/graphql/schema/timeout.rb +24 -28
  95. data/lib/graphql/schema/type_membership.rb +3 -0
  96. data/lib/graphql/schema/union.rb +10 -17
  97. data/lib/graphql/schema/warden.rb +34 -8
  98. data/lib/graphql/schema/wrapper.rb +0 -5
  99. data/lib/graphql/schema.rb +241 -973
  100. data/lib/graphql/static_validation/all_rules.rb +1 -0
  101. data/lib/graphql/static_validation/base_visitor.rb +4 -21
  102. data/lib/graphql/static_validation/definition_dependencies.rb +7 -1
  103. data/lib/graphql/static_validation/error.rb +2 -2
  104. data/lib/graphql/static_validation/literal_validator.rb +19 -1
  105. data/lib/graphql/static_validation/rules/directives_are_defined.rb +11 -5
  106. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +12 -12
  107. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +66 -0
  108. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +29 -0
  109. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +12 -6
  110. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +1 -1
  111. data/lib/graphql/static_validation/validator.rb +3 -25
  112. data/lib/graphql/static_validation.rb +0 -2
  113. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +7 -1
  114. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +38 -1
  115. data/lib/graphql/subscriptions/event.rb +3 -8
  116. data/lib/graphql/subscriptions/instrumentation.rb +0 -51
  117. data/lib/graphql/subscriptions.rb +32 -20
  118. data/lib/graphql/tracing/active_support_notifications_trace.rb +16 -0
  119. data/lib/graphql/tracing/appoptics_trace.rb +231 -0
  120. data/lib/graphql/tracing/appsignal_trace.rb +71 -0
  121. data/lib/graphql/tracing/data_dog_trace.rb +148 -0
  122. data/lib/graphql/tracing/data_dog_tracing.rb +2 -0
  123. data/lib/graphql/tracing/new_relic_trace.rb +75 -0
  124. data/lib/graphql/tracing/notifications_trace.rb +41 -0
  125. data/lib/graphql/tracing/platform_trace.rb +107 -0
  126. data/lib/graphql/tracing/platform_tracing.rb +26 -40
  127. data/lib/graphql/tracing/prometheus_trace.rb +89 -0
  128. data/lib/graphql/tracing/prometheus_tracing.rb +3 -3
  129. data/lib/graphql/tracing/scout_trace.rb +72 -0
  130. data/lib/graphql/tracing/statsd_trace.rb +56 -0
  131. data/lib/graphql/tracing.rb +136 -40
  132. data/lib/graphql/type_kinds.rb +6 -3
  133. data/lib/graphql/types/iso_8601_date.rb +4 -1
  134. data/lib/graphql/types/iso_8601_date_time.rb +4 -0
  135. data/lib/graphql/types/relay/base_connection.rb +16 -6
  136. data/lib/graphql/types/relay/connection_behaviors.rb +29 -27
  137. data/lib/graphql/types/relay/edge_behaviors.rb +16 -5
  138. data/lib/graphql/types/relay/node_behaviors.rb +12 -2
  139. data/lib/graphql/types/relay/page_info_behaviors.rb +7 -2
  140. data/lib/graphql/types/relay.rb +0 -3
  141. data/lib/graphql/types/string.rb +1 -1
  142. data/lib/graphql/version.rb +1 -1
  143. data/lib/graphql.rb +13 -74
  144. metadata +30 -133
  145. data/lib/graphql/analysis/analyze_query.rb +0 -98
  146. data/lib/graphql/analysis/field_usage.rb +0 -45
  147. data/lib/graphql/analysis/max_query_complexity.rb +0 -26
  148. data/lib/graphql/analysis/max_query_depth.rb +0 -26
  149. data/lib/graphql/analysis/query_complexity.rb +0 -88
  150. data/lib/graphql/analysis/query_depth.rb +0 -43
  151. data/lib/graphql/analysis/reducer_state.rb +0 -48
  152. data/lib/graphql/argument.rb +0 -131
  153. data/lib/graphql/authorization.rb +0 -82
  154. data/lib/graphql/backtrace/legacy_tracer.rb +0 -56
  155. data/lib/graphql/backwards_compatibility.rb +0 -61
  156. data/lib/graphql/base_type.rb +0 -232
  157. data/lib/graphql/boolean_type.rb +0 -2
  158. data/lib/graphql/compatibility/execution_specification/counter_schema.rb +0 -53
  159. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +0 -200
  160. data/lib/graphql/compatibility/execution_specification.rb +0 -436
  161. data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +0 -111
  162. data/lib/graphql/compatibility/lazy_execution_specification.rb +0 -215
  163. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -87
  164. data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +0 -79
  165. data/lib/graphql/compatibility/query_parser_specification.rb +0 -266
  166. data/lib/graphql/compatibility/schema_parser_specification.rb +0 -682
  167. data/lib/graphql/compatibility.rb +0 -5
  168. data/lib/graphql/define/assign_argument.rb +0 -12
  169. data/lib/graphql/define/assign_connection.rb +0 -13
  170. data/lib/graphql/define/assign_enum_value.rb +0 -18
  171. data/lib/graphql/define/assign_global_id_field.rb +0 -11
  172. data/lib/graphql/define/assign_mutation_function.rb +0 -34
  173. data/lib/graphql/define/assign_object_field.rb +0 -42
  174. data/lib/graphql/define/defined_object_proxy.rb +0 -53
  175. data/lib/graphql/define/instance_definable.rb +0 -255
  176. data/lib/graphql/define/no_definition_error.rb +0 -7
  177. data/lib/graphql/define/non_null_with_bang.rb +0 -16
  178. data/lib/graphql/define/type_definer.rb +0 -31
  179. data/lib/graphql/define.rb +0 -31
  180. data/lib/graphql/deprecated_dsl.rb +0 -55
  181. data/lib/graphql/directive/deprecated_directive.rb +0 -2
  182. data/lib/graphql/directive/include_directive.rb +0 -2
  183. data/lib/graphql/directive/skip_directive.rb +0 -2
  184. data/lib/graphql/directive.rb +0 -107
  185. data/lib/graphql/enum_type.rb +0 -133
  186. data/lib/graphql/execution/execute.rb +0 -333
  187. data/lib/graphql/execution/flatten.rb +0 -40
  188. data/lib/graphql/execution/instrumentation.rb +0 -92
  189. data/lib/graphql/execution/lazy/resolve.rb +0 -91
  190. data/lib/graphql/execution/typecast.rb +0 -50
  191. data/lib/graphql/field/resolve.rb +0 -59
  192. data/lib/graphql/field.rb +0 -226
  193. data/lib/graphql/float_type.rb +0 -2
  194. data/lib/graphql/function.rb +0 -128
  195. data/lib/graphql/id_type.rb +0 -2
  196. data/lib/graphql/input_object_type.rb +0 -138
  197. data/lib/graphql/int_type.rb +0 -2
  198. data/lib/graphql/interface_type.rb +0 -72
  199. data/lib/graphql/internal_representation/document.rb +0 -27
  200. data/lib/graphql/internal_representation/node.rb +0 -206
  201. data/lib/graphql/internal_representation/print.rb +0 -51
  202. data/lib/graphql/internal_representation/rewrite.rb +0 -184
  203. data/lib/graphql/internal_representation/scope.rb +0 -88
  204. data/lib/graphql/internal_representation/visit.rb +0 -36
  205. data/lib/graphql/internal_representation.rb +0 -7
  206. data/lib/graphql/language/lexer.rl +0 -260
  207. data/lib/graphql/list_type.rb +0 -80
  208. data/lib/graphql/non_null_type.rb +0 -71
  209. data/lib/graphql/object_type.rb +0 -130
  210. data/lib/graphql/query/arguments.rb +0 -189
  211. data/lib/graphql/query/arguments_cache.rb +0 -24
  212. data/lib/graphql/query/executor.rb +0 -52
  213. data/lib/graphql/query/literal_input.rb +0 -136
  214. data/lib/graphql/query/serial_execution/field_resolution.rb +0 -92
  215. data/lib/graphql/query/serial_execution/operation_resolution.rb +0 -19
  216. data/lib/graphql/query/serial_execution/selection_resolution.rb +0 -23
  217. data/lib/graphql/query/serial_execution/value_resolution.rb +0 -87
  218. data/lib/graphql/query/serial_execution.rb +0 -40
  219. data/lib/graphql/relay/array_connection.rb +0 -83
  220. data/lib/graphql/relay/base_connection.rb +0 -189
  221. data/lib/graphql/relay/connection_instrumentation.rb +0 -54
  222. data/lib/graphql/relay/connection_resolve.rb +0 -43
  223. data/lib/graphql/relay/connection_type.rb +0 -54
  224. data/lib/graphql/relay/edge.rb +0 -27
  225. data/lib/graphql/relay/edge_type.rb +0 -19
  226. data/lib/graphql/relay/edges_instrumentation.rb +0 -39
  227. data/lib/graphql/relay/global_id_resolve.rb +0 -17
  228. data/lib/graphql/relay/mongo_relation_connection.rb +0 -50
  229. data/lib/graphql/relay/mutation/instrumentation.rb +0 -23
  230. data/lib/graphql/relay/mutation/resolve.rb +0 -56
  231. data/lib/graphql/relay/mutation/result.rb +0 -38
  232. data/lib/graphql/relay/mutation.rb +0 -106
  233. data/lib/graphql/relay/node.rb +0 -39
  234. data/lib/graphql/relay/page_info.rb +0 -7
  235. data/lib/graphql/relay/relation_connection.rb +0 -188
  236. data/lib/graphql/relay/type_extensions.rb +0 -32
  237. data/lib/graphql/scalar_type.rb +0 -91
  238. data/lib/graphql/schema/catchall_middleware.rb +0 -35
  239. data/lib/graphql/schema/default_parse_error.rb +0 -10
  240. data/lib/graphql/schema/default_type_error.rb +0 -17
  241. data/lib/graphql/schema/member/accepts_definition.rb +0 -164
  242. data/lib/graphql/schema/member/cached_graphql_definition.rb +0 -58
  243. data/lib/graphql/schema/member/instrumentation.rb +0 -131
  244. data/lib/graphql/schema/middleware_chain.rb +0 -82
  245. data/lib/graphql/schema/possible_types.rb +0 -44
  246. data/lib/graphql/schema/rescue_middleware.rb +0 -60
  247. data/lib/graphql/schema/timeout_middleware.rb +0 -88
  248. data/lib/graphql/schema/traversal.rb +0 -228
  249. data/lib/graphql/schema/validation.rb +0 -313
  250. data/lib/graphql/static_validation/default_visitor.rb +0 -15
  251. data/lib/graphql/static_validation/no_validate_visitor.rb +0 -10
  252. data/lib/graphql/string_type.rb +0 -2
  253. data/lib/graphql/subscriptions/subscription_root.rb +0 -76
  254. data/lib/graphql/tracing/skylight_tracing.rb +0 -70
  255. data/lib/graphql/types/relay/default_relay.rb +0 -31
  256. data/lib/graphql/types/relay/node_field.rb +0 -24
  257. data/lib/graphql/types/relay/nodes_field.rb +0 -43
  258. data/lib/graphql/union_type.rb +0 -115
  259. data/lib/graphql/upgrader/member.rb +0 -937
  260. data/lib/graphql/upgrader/schema.rb +0 -38
@@ -5,9 +5,8 @@ require "graphql/schema/field/scope_extension"
5
5
  module GraphQL
6
6
  class Schema
7
7
  class Field
8
- include GraphQL::Schema::Member::CachedGraphQLDefinition
9
- include GraphQL::Schema::Member::AcceptsDefinition
10
8
  include GraphQL::Schema::Member::HasArguments
9
+ include GraphQL::Schema::Member::HasArguments::FieldConfigured
11
10
  include GraphQL::Schema::Member::HasAstNode
12
11
  include GraphQL::Schema::Member::HasPath
13
12
  include GraphQL::Schema::Member::HasValidators
@@ -30,8 +29,17 @@ module GraphQL
30
29
  # @return [String] Method or hash key on the underlying object to look up
31
30
  attr_reader :method_str
32
31
 
32
+ attr_reader :hash_key
33
+ attr_reader :dig_keys
34
+
33
35
  # @return [Symbol] The method on the type to look up
34
- attr_reader :resolver_method
36
+ def resolver_method
37
+ if @resolver_class
38
+ @resolver_class.resolver_method
39
+ else
40
+ @resolver_method
41
+ end
42
+ end
35
43
 
36
44
  # @return [Class] The thing this field was defined on (type, mutation, resolver)
37
45
  attr_accessor :owner
@@ -70,7 +78,10 @@ module GraphQL
70
78
  attr_reader :trace
71
79
 
72
80
  # @return [String, nil]
73
- attr_accessor :subscription_scope
81
+ def subscription_scope
82
+ @subscription_scope || (@resolver_class.respond_to?(:subscription_scope) ? @resolver_class.subscription_scope : nil)
83
+ end
84
+ attr_writer :subscription_scope
74
85
 
75
86
  # Create a field instance from a list of arguments, keyword arguments, and a block.
76
87
  #
@@ -84,21 +95,9 @@ module GraphQL
84
95
  # @return [GraphQL::Schema:Field] an instance of `self
85
96
  # @see {.initialize} for other options
86
97
  def self.from_options(name = nil, type = nil, desc = nil, resolver: nil, mutation: nil, subscription: nil,**kwargs, &block)
87
- if kwargs[:field]
88
- if kwargs[:field].is_a?(GraphQL::Field) && kwargs[:field] == GraphQL::Types::Relay::NodeField.graphql_definition
89
- GraphQL::Deprecation.warn("Legacy-style `GraphQL::Relay::Node.field` is being added to a class-based type. See `GraphQL::Types::Relay::NodeField` for a replacement.")
90
- return GraphQL::Types::Relay::NodeField
91
- elsif kwargs[:field].is_a?(GraphQL::Field) && kwargs[:field] == GraphQL::Types::Relay::NodesField.graphql_definition
92
- GraphQL::Deprecation.warn("Legacy-style `GraphQL::Relay::Node.plural_field` is being added to a class-based type. See `GraphQL::Types::Relay::NodesField` for a replacement.")
93
- return GraphQL::Types::Relay::NodesField
94
- end
95
- end
96
-
97
- if (parent_config = resolver || mutation || subscription)
98
- # Get the parent config, merge in local overrides
99
- kwargs = parent_config.field_options.merge(kwargs)
98
+ if (resolver_class = resolver || mutation || subscription)
100
99
  # Add a reference to that parent class
101
- kwargs[:resolver_class] = parent_config
100
+ kwargs[:resolver_class] = resolver_class
102
101
  end
103
102
 
104
103
  if name
@@ -106,9 +105,6 @@ module GraphQL
106
105
  end
107
106
 
108
107
  if !type.nil?
109
- if type.is_a?(GraphQL::Field)
110
- raise ArgumentError, "A GraphQL::Field was passed as the second argument, use the `field:` keyword for this instead."
111
- end
112
108
  if desc
113
109
  if kwargs[:description]
114
110
  raise ArgumentError, "Provide description as a positional argument or `description:` keyword, but not both (#{desc.inspect}, #{kwargs[:description].inspect})"
@@ -116,8 +112,8 @@ module GraphQL
116
112
 
117
113
  kwargs[:description] = desc
118
114
  kwargs[:type] = type
119
- elsif (kwargs[:field] || kwargs[:function] || resolver || mutation) && type.is_a?(String)
120
- # The return type should be copied from `field` or `function`, and the second positional argument is the description
115
+ elsif (resolver || mutation) && type.is_a?(String)
116
+ # The return type should be copied from the resolver, and the second positional argument is the description
121
117
  kwargs[:description] = type
122
118
  else
123
119
  kwargs[:type] = type
@@ -134,10 +130,10 @@ module GraphQL
134
130
  def connection?
135
131
  if @connection.nil?
136
132
  # Provide default based on type name
137
- return_type_name = if (contains_type = @field || @function)
138
- Member::BuildType.to_type_name(contains_type.type)
139
- elsif @return_type_expr
133
+ return_type_name = if @return_type_expr
140
134
  Member::BuildType.to_type_name(@return_type_expr)
135
+ elsif @resolver_class && @resolver_class.type
136
+ Member::BuildType.to_type_name(@resolver_class.type)
141
137
  else
142
138
  # As a last ditch, try to force loading the return type:
143
139
  type.unwrap.name
@@ -153,8 +149,18 @@ module GraphQL
153
149
  if !@scope.nil?
154
150
  # The default was overridden
155
151
  @scope
152
+ elsif @return_type_expr
153
+ # Detect a list return type, but don't call `type` since that may eager-load an otherwise lazy-loaded type
154
+ @return_type_expr.is_a?(Array) ||
155
+ (@return_type_expr.is_a?(String) && @return_type_expr.include?("[")) ||
156
+ connection?
157
+ elsif @resolver_class
158
+ resolver_type = @resolver_class.type_expr
159
+ resolver_type.is_a?(Array) ||
160
+ (resolver_type.is_a?(String) && resolver_type.include?("[")) ||
161
+ connection?
156
162
  else
157
- @return_type_expr && (@return_type_expr.is_a?(Array) || (@return_type_expr.is_a?(String) && @return_type_expr.include?("[")) || connection?)
163
+ false
158
164
  end
159
165
  end
160
166
 
@@ -187,7 +193,7 @@ module GraphQL
187
193
  # @param name [Symbol] The underscore-cased version of this field name (will be camelized for the GraphQL API)
188
194
  # @param type [Class, GraphQL::BaseType, Array] The return type of this field
189
195
  # @param owner [Class] The type that this field belongs to
190
- # @param null [Boolean] `true` if this field may return `null`, `false` if it is never `null`
196
+ # @param null [Boolean] (defaults to `true`) `true` if this field may return `null`, `false` if it is never `null`
191
197
  # @param description [String] Field description
192
198
  # @param deprecation_reason [String] If present, the field is marked "deprecated" with this message
193
199
  # @param method [Symbol] The method to call on the underlying object to resolve this field (defaults to `name`)
@@ -197,10 +203,8 @@ module GraphQL
197
203
  # @param connection [Boolean] `true` if this field should get automagic connection behavior; default is to infer by `*Connection` in the return type name
198
204
  # @param connection_extension [Class] The extension to add, to implement connections. If `nil`, no extension is added.
199
205
  # @param max_page_size [Integer, nil] For connections, the maximum number of items to return from this field, or `nil` to allow unlimited results.
206
+ # @param default_page_size [Integer, nil] For connections, the default number of items to return from this field, or `nil` to return unlimited results.
200
207
  # @param introspection [Boolean] If true, this field will be marked as `#introspection?` and the name may begin with `__`
201
- # @param resolve [<#call(obj, args, ctx)>] **deprecated** for compatibility with <1.8.0
202
- # @param field [GraphQL::Field, GraphQL::Schema::Field] **deprecated** for compatibility with <1.8.0
203
- # @param function [GraphQL::Function] **deprecated** for compatibility with <1.8.0
204
208
  # @param resolver_class [Class] (Private) A {Schema::Resolver} which this field was derived from. Use `resolver:` to create a field with a resolver.
205
209
  # @param arguments [{String=>GraphQL::Schema::Argument, Hash}] Arguments for this field (may be added in the block, also)
206
210
  # @param camelize [Boolean] If true, the field name will be camelized when building the schema
@@ -214,31 +218,25 @@ module GraphQL
214
218
  # @param ast_node [Language::Nodes::FieldDefinition, nil] If this schema was parsed from definition, this AST node defined the field
215
219
  # @param method_conflict_warning [Boolean] If false, skip the warning if this field's method conflicts with a built-in method
216
220
  # @param validates [Array<Hash>] Configurations for validating this field
217
- # @param legacy_edge_class [Class, nil] (DEPRECATED) If present, pass this along to the legacy field definition
218
- def initialize(type: nil, name: nil, owner: nil, null: true, field: nil, function: nil, description: nil, deprecation_reason: nil, method: nil, hash_key: nil, dig: nil, resolver_method: nil, resolve: nil, connection: nil, max_page_size: :not_given, scope: nil, introspection: false, camelize: true, trace: nil, complexity: 1, ast_node: nil, extras: EMPTY_ARRAY, extensions: EMPTY_ARRAY, connection_extension: self.class.connection_extension, resolver_class: nil, subscription_scope: nil, relay_node_field: false, relay_nodes_field: false, method_conflict_warning: true, broadcastable: nil, arguments: EMPTY_HASH, directives: EMPTY_HASH, validates: EMPTY_ARRAY, legacy_edge_class: nil, &definition_block)
221
+ # @fallback_value [Object] A fallback value if the method is not defined
222
+ def initialize(type: nil, name: nil, owner: nil, null: nil, description: NOT_CONFIGURED, deprecation_reason: nil, method: nil, hash_key: nil, dig: nil, resolver_method: nil, connection: nil, max_page_size: NOT_CONFIGURED, default_page_size: NOT_CONFIGURED, scope: nil, introspection: false, camelize: true, trace: nil, complexity: nil, ast_node: nil, extras: EMPTY_ARRAY, extensions: EMPTY_ARRAY, connection_extension: self.class.connection_extension, resolver_class: nil, subscription_scope: nil, relay_node_field: false, relay_nodes_field: false, method_conflict_warning: true, broadcastable: NOT_CONFIGURED, arguments: EMPTY_HASH, directives: EMPTY_HASH, validates: EMPTY_ARRAY, fallback_value: :not_given, &definition_block)
219
223
  if name.nil?
220
224
  raise ArgumentError, "missing first `name` argument or keyword `name:`"
221
225
  end
222
- if !(field || function || resolver_class)
226
+ if !(resolver_class)
223
227
  if type.nil?
224
228
  raise ArgumentError, "missing second `type` argument or keyword `type:`"
225
229
  end
226
230
  end
227
- if (field || function || resolve) && extras.any?
228
- raise ArgumentError, "keyword `extras:` may only be used with method-based resolve and class-based field such as mutation class, please remove `field:`, `function:` or `resolve:`"
229
- end
230
231
  @original_name = name
231
232
  name_s = -name.to_s
233
+
232
234
  @underscored_name = -Member::BuildType.underscore(name_s)
233
235
  @name = -(camelize ? Member::BuildType.camelize(name_s) : name_s)
236
+
234
237
  @description = description
235
- if field.is_a?(GraphQL::Schema::Field)
236
- raise ArgumentError, "Instead of passing a field as `field:`, use `add_field(field)` to add an already-defined field."
237
- else
238
- @field = field
239
- end
240
- @function = function
241
- @resolve = resolve
238
+ @type = @owner_type = @own_validators = @own_directives = @own_arguments = nil # these will be prepared later if necessary
239
+
242
240
  self.deprecation_reason = deprecation_reason
243
241
 
244
242
  if method && hash_key && dig
@@ -255,20 +253,31 @@ module GraphQL
255
253
  end
256
254
  end
257
255
 
258
- # TODO: I think non-string/symbol hash keys are wrongly normalized (eg `1` will not work)
259
256
  method_name = method || hash_key || name_s
260
257
  @dig_keys = dig
261
- resolver_method ||= name_s.to_sym
258
+ if hash_key
259
+ @hash_key = hash_key
260
+ @hash_key_str = hash_key.to_s
261
+ else
262
+ @hash_key = NOT_CONFIGURED
263
+ @hash_key_str = NOT_CONFIGURED
264
+ end
262
265
 
263
266
  @method_str = -method_name.to_s
264
267
  @method_sym = method_name.to_sym
265
- @resolver_method = resolver_method
268
+ @resolver_method = (resolver_method || name_s).to_sym
266
269
  @complexity = complexity
267
270
  @return_type_expr = type
268
- @return_type_null = null
271
+ @return_type_null = if !null.nil?
272
+ null
273
+ elsif resolver_class
274
+ nil
275
+ else
276
+ true
277
+ end
269
278
  @connection = connection
270
- @has_max_page_size = max_page_size != :not_given
271
- @max_page_size = max_page_size == :not_given ? nil : max_page_size
279
+ @max_page_size = max_page_size
280
+ @default_page_size = default_page_size
272
281
  @introspection = introspection
273
282
  @extras = extras
274
283
  @broadcastable = broadcastable
@@ -279,7 +288,7 @@ module GraphQL
279
288
  @relay_nodes_field = relay_nodes_field
280
289
  @ast_node = ast_node
281
290
  @method_conflict_warning = method_conflict_warning
282
- @legacy_edge_class = legacy_edge_class
291
+ @fallback_value = fallback_value
283
292
 
284
293
  arguments.each do |name, arg|
285
294
  case arg
@@ -316,13 +325,19 @@ module GraphQL
316
325
  self.extensions(extensions)
317
326
  end
318
327
 
328
+ if resolver_class && resolver_class.extensions.any?
329
+ self.extensions(resolver_class.extensions)
330
+ end
331
+
319
332
  if directives.any?
320
333
  directives.each do |(dir_class, options)|
321
334
  self.directive(dir_class, **options)
322
335
  end
323
336
  end
324
337
 
325
- self.validates(validates)
338
+ if !validates.empty?
339
+ self.validates(validates)
340
+ end
326
341
 
327
342
  if definition_block
328
343
  if definition_block.arity == 1
@@ -340,7 +355,13 @@ module GraphQL
340
355
  # @return [Boolean, nil]
341
356
  # @see GraphQL::Subscriptions::BroadcastAnalyzer
342
357
  def broadcastable?
343
- @broadcastable
358
+ if !NOT_CONFIGURED.equal?(@broadcastable)
359
+ @broadcastable
360
+ elsif @resolver_class
361
+ @resolver_class.broadcastable?
362
+ else
363
+ nil
364
+ end
344
365
  end
345
366
 
346
367
  # @param text [String]
@@ -348,8 +369,12 @@ module GraphQL
348
369
  def description(text = nil)
349
370
  if text
350
371
  @description = text
351
- else
372
+ elsif !NOT_CONFIGURED.equal?(@description)
352
373
  @description
374
+ elsif @resolver_class
375
+ @resolver_class.description
376
+ else
377
+ nil
353
378
  end
354
379
  end
355
380
 
@@ -413,7 +438,12 @@ module GraphQL
413
438
  def extras(new_extras = nil)
414
439
  if new_extras.nil?
415
440
  # Read the value
416
- @extras
441
+ field_extras = @extras
442
+ if @resolver_class && @resolver_class.extras.any?
443
+ field_extras + @resolver_class.extras
444
+ else
445
+ field_extras
446
+ end
417
447
  else
418
448
  if @extras.frozen?
419
449
  @extras = @extras.dup
@@ -441,11 +471,11 @@ module GraphQL
441
471
  end
442
472
 
443
473
  if max_possible_page_size.nil?
444
- max_possible_page_size = max_page_size || query.schema.default_max_page_size
474
+ max_possible_page_size = default_page_size || query.schema.default_page_size || max_page_size || query.schema.default_max_page_size
445
475
  end
446
476
 
447
477
  if max_possible_page_size.nil?
448
- raise GraphQL::Error, "Can't calculate complexity for #{path}, no `first:`, `last:`, `max_page_size` or `default_max_page_size`"
478
+ raise GraphQL::Error, "Can't calculate complexity for #{path}, no `first:`, `last:`, `default_page_size`, `max_page_size` or `default_max_page_size`"
449
479
  else
450
480
  metadata_complexity = 0
451
481
  lookahead = GraphQL::Execution::Lookahead.new(query: query, field: self, ast_nodes: nodes, owner_type: owner)
@@ -502,7 +532,11 @@ module GraphQL
502
532
  when Numeric
503
533
  @complexity = new_complexity
504
534
  when nil
505
- @complexity
535
+ if @resolver_class
536
+ @complexity || @resolver_class.complexity || 1
537
+ else
538
+ @complexity || 1
539
+ end
506
540
  else
507
541
  raise("Invalid complexity: #{new_complexity.inspect} on #{@name}")
508
542
  end
@@ -510,105 +544,49 @@ module GraphQL
510
544
 
511
545
  # @return [Boolean] True if this field's {#max_page_size} should override the schema default.
512
546
  def has_max_page_size?
513
- @has_max_page_size
547
+ !NOT_CONFIGURED.equal?(@max_page_size) || (@resolver_class && @resolver_class.has_max_page_size?)
514
548
  end
515
549
 
516
550
  # @return [Integer, nil] Applied to connections if {#has_max_page_size?}
517
- attr_reader :max_page_size
518
-
519
- prepend Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
520
-
521
- # @return [GraphQL::Field]
522
- def to_graphql
523
- field_defn = if @field
524
- @field.dup
525
- elsif @function
526
- GraphQL::Function.build_field(@function)
551
+ def max_page_size
552
+ if !NOT_CONFIGURED.equal?(@max_page_size)
553
+ @max_page_size
554
+ elsif @resolver_class && @resolver_class.has_max_page_size?
555
+ @resolver_class.max_page_size
527
556
  else
528
- GraphQL::Field.new
529
- end
530
-
531
- field_defn.name = @name
532
- if @return_type_expr
533
- field_defn.type = -> { type }
557
+ nil
534
558
  end
559
+ end
535
560
 
536
- if @description
537
- field_defn.description = @description
538
- end
539
-
540
- if self.deprecation_reason
541
- field_defn.deprecation_reason = self.deprecation_reason
542
- end
543
-
544
- if @resolver_class
545
- if @resolver_class < GraphQL::Schema::Mutation
546
- field_defn.mutation = @resolver_class
547
- end
548
- field_defn.metadata[:resolver] = @resolver_class
549
- end
550
-
551
- if !@trace.nil?
552
- field_defn.trace = @trace
553
- end
554
-
555
- if @relay_node_field
556
- field_defn.relay_node_field = @relay_node_field
557
- end
558
-
559
- if @relay_nodes_field
560
- field_defn.relay_nodes_field = @relay_nodes_field
561
- end
562
-
563
- if @legacy_edge_class
564
- field_defn.edge_class = @legacy_edge_class
565
- end
566
-
567
- field_defn.resolve = self.method(:resolve_field)
568
- field_defn.connection = connection?
569
- field_defn.connection_max_page_size = max_page_size
570
- field_defn.introspection = @introspection
571
- field_defn.complexity = @complexity
572
- field_defn.subscription_scope = @subscription_scope
573
- field_defn.ast_node = ast_node
574
-
575
- all_argument_definitions.each do |defn|
576
- arg_graphql = defn.deprecated_to_graphql
577
- field_defn.arguments[arg_graphql.name] = arg_graphql # rubocop:disable Development/ContextIsPassedCop -- legacy-related
578
- end
561
+ # @return [Boolean] True if this field's {#default_page_size} should override the schema default.
562
+ def has_default_page_size?
563
+ !NOT_CONFIGURED.equal?(@default_page_size) || (@resolver_class && @resolver_class.has_default_page_size?)
564
+ end
579
565
 
580
- # Support a passed-in proc, one way or another
581
- @resolve_proc = if @resolve
582
- @resolve
583
- elsif @function
584
- @function
585
- elsif @field
586
- @field.resolve_proc
566
+ # @return [Integer, nil] Applied to connections if {#has_default_page_size?}
567
+ def default_page_size
568
+ if !NOT_CONFIGURED.equal?(@default_page_size)
569
+ @default_page_size
570
+ elsif @resolver_class && @resolver_class.has_default_page_size?
571
+ @resolver_class.default_page_size
572
+ else
573
+ nil
587
574
  end
588
-
589
- # Ok, `self` isn't a class, but this is for consistency with the classes
590
- field_defn.metadata[:type_class] = self
591
- field_defn.arguments_class = GraphQL::Query::Arguments.construct_arguments_class(field_defn)
592
- field_defn
593
575
  end
594
576
 
595
577
  class MissingReturnTypeError < GraphQL::Error; end
596
578
  attr_writer :type
597
579
 
598
580
  def type
599
- @type ||= if @function
600
- Member::BuildType.parse_type(@function.type, null: false)
601
- elsif @field
602
- Member::BuildType.parse_type(@field.type, null: false)
603
- elsif @return_type_expr.nil?
604
- # Not enough info to determine type
605
- message = "Can't determine the return type for #{self.path}"
606
- if @resolver_class
607
- message += " (it has `resolver: #{@resolver_class}`, consider configuration a `type ...` for that class)"
581
+ if @resolver_class
582
+ return_type = @return_type_expr || @resolver_class.type_expr
583
+ if return_type.nil?
584
+ raise MissingReturnTypeError, "Can't determine the return type for #{self.path} (it has `resolver: #{@resolver_class}`, perhaps that class is missing a `type ...` declaration, or perhaps its type causes a cyclical loading issue)"
608
585
  end
609
- raise MissingReturnTypeError, message
586
+ nullable = @return_type_null.nil? ? @resolver_class.null : @return_type_null
587
+ Member::BuildType.parse_type(return_type, null: nullable)
610
588
  else
611
- Member::BuildType.parse_type(@return_type_expr, null: @return_type_null)
589
+ @type ||= Member::BuildType.parse_type(@return_type_expr, null: @return_type_null)
612
590
  end
613
591
  rescue GraphQL::Schema::InvalidDocumentError, MissingReturnTypeError => err
614
592
  # Let this propagate up
@@ -625,14 +603,6 @@ module GraphQL
625
603
  end
626
604
  end
627
605
 
628
- def accessible?(context)
629
- if @resolver_class
630
- @resolver_class.accessible?(context)
631
- else
632
- true
633
- end
634
- end
635
-
636
606
  def authorized?(object, args, context)
637
607
  if @resolver_class
638
608
  # The resolver _instance_ will check itself during `resolve()`
@@ -646,62 +616,33 @@ module GraphQL
646
616
  arg_values = args
647
617
  using_arg_values = false
648
618
  end
649
- # Faster than `.any?`
650
- arguments(context).each_value do |arg|
651
- arg_key = arg.keyword
652
- if arg_values.key?(arg_key)
653
- arg_value = arg_values[arg_key]
654
- if using_arg_values
655
- if arg_value.default_used?
656
- # pass -- no auth required for default used
657
- next
658
- else
659
- application_arg_value = arg_value.value
660
- if application_arg_value.is_a?(GraphQL::Execution::Interpreter::Arguments)
661
- application_arg_value.keyword_arguments
619
+ if args.size > 0
620
+ args = context.warden.arguments(self)
621
+ args.each do |arg|
622
+ arg_key = arg.keyword
623
+ if arg_values.key?(arg_key)
624
+ arg_value = arg_values[arg_key]
625
+ if using_arg_values
626
+ if arg_value.default_used?
627
+ # pass -- no auth required for default used
628
+ next
629
+ else
630
+ application_arg_value = arg_value.value
631
+ if application_arg_value.is_a?(GraphQL::Execution::Interpreter::Arguments)
632
+ application_arg_value.keyword_arguments
633
+ end
662
634
  end
635
+ else
636
+ application_arg_value = arg_value
663
637
  end
664
- else
665
- application_arg_value = arg_value
666
- end
667
-
668
- if !arg.authorized?(object, application_arg_value, context)
669
- return false
670
- end
671
- end
672
- end
673
- true
674
- end
675
- end
676
638
 
677
- # Implement {GraphQL::Field}'s resolve API.
678
- #
679
- # Eventually, we might hook up field instances to execution in another way. TBD.
680
- # @see #resolve for how the interpreter hooks up to it
681
- def resolve_field(obj, args, ctx)
682
- ctx.schema.after_lazy(obj) do |after_obj|
683
- # First, apply auth ...
684
- query_ctx = ctx.query.context
685
- # Some legacy fields can have `nil` here, not exactly sure why.
686
- # @see https://github.com/rmosolgo/graphql-ruby/issues/1990 before removing
687
- inner_obj = after_obj && after_obj.object
688
- ctx.schema.after_lazy(to_ruby_args(after_obj, args, ctx)) do |ruby_args|
689
- if authorized?(inner_obj, ruby_args, query_ctx)
690
- # Then if it passed, resolve the field
691
- if @resolve_proc
692
- # Might be nil, still want to call the func in that case
693
- with_extensions(inner_obj, ruby_args, query_ctx) do |extended_obj, extended_args|
694
- # Pass the GraphQL args here for compatibility:
695
- @resolve_proc.call(extended_obj, args, ctx)
639
+ if !arg.authorized?(object, application_arg_value, context)
640
+ return false
696
641
  end
697
- else
698
- public_send_field(after_obj, ruby_args, query_ctx)
699
642
  end
700
- else
701
- err = GraphQL::UnauthorizedFieldError.new(object: inner_obj, type: obj.class, context: ctx, field: self)
702
- query_ctx.schema.unauthorized_field(err)
703
643
  end
704
644
  end
645
+ true
705
646
  end
706
647
  end
707
648
 
@@ -710,34 +651,112 @@ module GraphQL
710
651
  # @param object [GraphQL::Schema::Object] An instance of some type class, wrapping an application object
711
652
  # @param args [Hash] A symbol-keyed hash of Ruby keyword arguments. (Empty if no args)
712
653
  # @param ctx [GraphQL::Query::Context]
713
- def resolve(object, args, ctx)
714
- if @resolve_proc
715
- raise "Can't run resolve proc for #{path} when using GraphQL::Execution::Interpreter"
716
- end
717
- begin
718
- # Unwrap the GraphQL object to get the application object.
719
- application_object = object.object
654
+ def resolve(object, args, query_ctx)
655
+ # Unwrap the GraphQL object to get the application object.
656
+ application_object = object.object
657
+ method_receiver = nil
658
+ method_to_call = nil
659
+ method_args = nil
660
+
661
+ Schema::Validator.validate!(validators, application_object, query_ctx, args)
662
+
663
+ query_ctx.schema.after_lazy(self.authorized?(application_object, args, query_ctx)) do |is_authorized|
664
+ if is_authorized
665
+ with_extensions(object, args, query_ctx) do |obj, ruby_kwargs|
666
+ method_args = ruby_kwargs
667
+ if @resolver_class
668
+ if obj.is_a?(GraphQL::Schema::Object)
669
+ obj = obj.object
670
+ end
671
+ obj = @resolver_class.new(object: obj, context: query_ctx, field: self)
672
+ end
720
673
 
721
- Schema::Validator.validate!(validators, application_object, ctx, args)
674
+ inner_object = obj.object
722
675
 
723
- ctx.schema.after_lazy(self.authorized?(application_object, args, ctx)) do |is_authorized|
724
- if is_authorized
725
- public_send_field(object, args, ctx)
726
- else
727
- raise GraphQL::UnauthorizedFieldError.new(object: application_object, type: object.class, context: ctx, field: self)
676
+ if !NOT_CONFIGURED.equal?(@hash_key)
677
+ hash_value = if inner_object.is_a?(Hash)
678
+ inner_object.key?(@hash_key) ? inner_object[@hash_key] : inner_object[@hash_key_str]
679
+ elsif inner_object.respond_to?(:[])
680
+ inner_object[@hash_key]
681
+ else
682
+ nil
683
+ end
684
+ if hash_value == false
685
+ hash_value
686
+ else
687
+ hash_value || (@fallback_value != :not_given ? @fallback_value : nil)
688
+ end
689
+ elsif obj.respond_to?(resolver_method)
690
+ method_to_call = resolver_method
691
+ method_receiver = obj
692
+ # Call the method with kwargs, if there are any
693
+ if ruby_kwargs.any?
694
+ obj.public_send(resolver_method, **ruby_kwargs)
695
+ else
696
+ obj.public_send(resolver_method)
697
+ end
698
+ elsif inner_object.is_a?(Hash)
699
+ if @dig_keys
700
+ inner_object.dig(*@dig_keys)
701
+ elsif inner_object.key?(@method_sym)
702
+ inner_object[@method_sym]
703
+ elsif inner_object.key?(@method_str)
704
+ inner_object[@method_str]
705
+ elsif @fallback_value != :not_given
706
+ @fallback_value
707
+ else
708
+ nil
709
+ end
710
+ elsif inner_object.respond_to?(@method_sym)
711
+ method_to_call = @method_sym
712
+ method_receiver = obj.object
713
+ if ruby_kwargs.any?
714
+ inner_object.public_send(@method_sym, **ruby_kwargs)
715
+ else
716
+ inner_object.public_send(@method_sym)
717
+ end
718
+ elsif @fallback_value != :not_given
719
+ @fallback_value
720
+ else
721
+ raise <<-ERR
722
+ Failed to implement #{@owner.graphql_name}.#{@name}, tried:
723
+
724
+ - `#{obj.class}##{resolver_method}`, which did not exist
725
+ - `#{inner_object.class}##{@method_sym}`, which did not exist
726
+ - Looking up hash key `#{@method_sym.inspect}` or `#{@method_str.inspect}` on `#{inner_object}`, but it wasn't a Hash
727
+
728
+ To implement this field, define one of the methods above (and check for typos), or supply a `fallback_value`.
729
+ ERR
730
+ end
728
731
  end
732
+ else
733
+ raise GraphQL::UnauthorizedFieldError.new(object: application_object, type: object.class, context: query_ctx, field: self)
729
734
  end
730
- rescue GraphQL::UnauthorizedFieldError => err
731
- err.field ||= self
732
- ctx.schema.unauthorized_field(err)
733
- rescue GraphQL::UnauthorizedError => err
734
- ctx.schema.unauthorized_object(err)
735
735
  end
736
+ rescue GraphQL::UnauthorizedFieldError => err
737
+ err.field ||= self
738
+ begin
739
+ query_ctx.schema.unauthorized_field(err)
740
+ rescue GraphQL::ExecutionError => err
741
+ err
742
+ end
743
+ rescue GraphQL::UnauthorizedError => err
744
+ begin
745
+ query_ctx.schema.unauthorized_object(err)
746
+ rescue GraphQL::ExecutionError => err
747
+ err
748
+ end
749
+ rescue ArgumentError
750
+ if method_receiver && method_to_call
751
+ assert_satisfactory_implementation(method_receiver, method_to_call, method_args)
752
+ end
753
+ # if the line above doesn't raise, re-raise
754
+ raise
736
755
  rescue GraphQL::ExecutionError => err
737
756
  err
738
757
  end
739
758
 
740
- # @param ctx [GraphQL::Query::Context::FieldResolutionContext]
759
+ # @param ctx [GraphQL::Query::Context]
741
760
  def fetch_extra(extra_name, ctx)
742
761
  if extra_name != :path && extra_name != :ast_node && respond_to?(extra_name)
743
762
  self.public_send(extra_name)
@@ -750,127 +769,6 @@ module GraphQL
750
769
 
751
770
  private
752
771
 
753
- NO_ARGS = {}.freeze
754
-
755
- # Convert a GraphQL arguments instance into a Ruby-style hash.
756
- #
757
- # @param obj [GraphQL::Schema::Object] The object where this field is being resolved
758
- # @param graphql_args [GraphQL::Query::Arguments]
759
- # @param field_ctx [GraphQL::Query::Context::FieldResolutionContext]
760
- # @return [Hash<Symbol => Any>]
761
- def to_ruby_args(obj, graphql_args, field_ctx)
762
- if graphql_args.any? || @extras.any?
763
- # Splat the GraphQL::Arguments to Ruby keyword arguments
764
- ruby_kwargs = graphql_args.to_kwargs
765
- maybe_lazies = []
766
- # Apply any `prepare` methods. Not great code organization, can this go somewhere better?
767
- arguments(field_ctx).each do |name, arg_defn|
768
- ruby_kwargs_key = arg_defn.keyword
769
-
770
- if ruby_kwargs.key?(ruby_kwargs_key)
771
- loads = arg_defn.loads
772
- value = ruby_kwargs[ruby_kwargs_key]
773
- loaded_value = if loads && !arg_defn.from_resolver?
774
- if arg_defn.type.list?
775
- loaded_values = value.map { |val| load_application_object(arg_defn, loads, val, field_ctx.query.context) }
776
- field_ctx.schema.after_any_lazies(loaded_values) { |result| result }
777
- else
778
- load_application_object(arg_defn, loads, value, field_ctx.query.context)
779
- end
780
- elsif arg_defn.type.list? && value.is_a?(Array)
781
- field_ctx.schema.after_any_lazies(value, &:itself)
782
- else
783
- value
784
- end
785
-
786
- maybe_lazies << field_ctx.schema.after_lazy(loaded_value) do |loaded_value|
787
- prepared_value = if arg_defn.prepare
788
- arg_defn.prepare_value(obj, loaded_value)
789
- else
790
- loaded_value
791
- end
792
-
793
- ruby_kwargs[ruby_kwargs_key] = prepared_value
794
- end
795
- end
796
- end
797
-
798
- @extras.each do |extra_arg|
799
- ruby_kwargs[extra_arg] = fetch_extra(extra_arg, field_ctx)
800
- end
801
-
802
- field_ctx.schema.after_any_lazies(maybe_lazies) do
803
- ruby_kwargs
804
- end
805
- else
806
- NO_ARGS
807
- end
808
- end
809
-
810
- def public_send_field(unextended_obj, unextended_ruby_kwargs, query_ctx)
811
- with_extensions(unextended_obj, unextended_ruby_kwargs, query_ctx) do |obj, ruby_kwargs|
812
- begin
813
- method_receiver = nil
814
- method_to_call = nil
815
- if @resolver_class
816
- if obj.is_a?(GraphQL::Schema::Object)
817
- obj = obj.object
818
- end
819
- obj = @resolver_class.new(object: obj, context: query_ctx, field: self)
820
- end
821
-
822
- # Find a way to resolve this field, checking:
823
- #
824
- # - A method on the type instance;
825
- # - Hash keys, if the wrapped object is a hash;
826
- # - A method on the wrapped object;
827
- # - Or, raise not implemented.
828
- #
829
- if obj.respond_to?(@resolver_method)
830
- method_to_call = @resolver_method
831
- method_receiver = obj
832
- # Call the method with kwargs, if there are any
833
- if ruby_kwargs.any?
834
- obj.public_send(@resolver_method, **ruby_kwargs)
835
- else
836
- obj.public_send(@resolver_method)
837
- end
838
- elsif obj.object.is_a?(Hash)
839
- inner_object = obj.object
840
- if @dig_keys
841
- inner_object.dig(*@dig_keys)
842
- elsif inner_object.key?(@method_sym)
843
- inner_object[@method_sym]
844
- else
845
- inner_object[@method_str]
846
- end
847
- elsif obj.object.respond_to?(@method_sym)
848
- method_to_call = @method_sym
849
- method_receiver = obj.object
850
- if ruby_kwargs.any?
851
- obj.object.public_send(@method_sym, **ruby_kwargs)
852
- else
853
- obj.object.public_send(@method_sym)
854
- end
855
- else
856
- raise <<-ERR
857
- Failed to implement #{@owner.graphql_name}.#{@name}, tried:
858
-
859
- - `#{obj.class}##{@resolver_method}`, which did not exist
860
- - `#{obj.object.class}##{@method_sym}`, which did not exist
861
- - Looking up hash key `#{@method_sym.inspect}` or `#{@method_str.inspect}` on `#{obj.object}`, but it wasn't a Hash
862
-
863
- To implement this field, define one of the methods above (and check for typos)
864
- ERR
865
- end
866
- rescue ArgumentError
867
- assert_satisfactory_implementation(method_receiver, method_to_call, ruby_kwargs)
868
- # if the line above doesn't raise, re-raise
869
- raise
870
- end
871
- end
872
- end
873
-
874
772
  def assert_satisfactory_implementation(receiver, method_name, ruby_kwargs)
875
773
  method_defn = receiver.method(method_name)
876
774
  unsatisfied_ruby_kwargs = ruby_kwargs.dup
@@ -901,7 +799,7 @@ module GraphQL
901
799
 
902
800
  if unsatisfied_ruby_kwargs.any? || unsatisfied_method_params.any?
903
801
  raise FieldImplementationFailed.new, <<-ERR
904
- Failed to call #{method_name} on #{receiver.inspect} because the Ruby method params were incompatible with the GraphQL arguments:
802
+ Failed to call `#{method_name.inspect}` on #{receiver.inspect} because the Ruby method params were incompatible with the GraphQL arguments:
905
803
 
906
804
  #{ unsatisfied_ruby_kwargs
907
805
  .map { |key, value| "- `#{key}: #{value}` was given by GraphQL but not defined in the Ruby method. Add `#{key}:` to the method parameters." }