Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions guides/execution/migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,12 +242,13 @@ Resolver classes are called.

### `raw_value` 🟡

Supported but requires a manual opt-in at schema level. Support for this will probably get better somehow in a future version.
Supported, but the `raw_value` call must be made on `context`, for example:

```ruby
class MyAppSchema < GraphQL::Schema
uses_raw_value(true) # TODO This configuration will be improved in a future GraphQL-Ruby version
use GraphQL::Execution::Next
field :values, SomeObjectType, resolve_static: true

def self.values(context)
context.raw_value(...)
end
```

Expand Down
4 changes: 1 addition & 3 deletions lib/graphql.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ def self.eager_load!
class Error < StandardError
end

class RuntimeError < Error
end

# This error is raised when GraphQL-Ruby encounters a situation
# that it *thought* would never happen. Please report this bug!
class InvariantError < Error
Expand Down Expand Up @@ -122,6 +119,7 @@ class << self
autoload :ParseError, "graphql/parse_error"
autoload :Backtrace, "graphql/backtrace"

autoload :RuntimeError, "graphql/runtime_error"
autoload :UnauthorizedError, "graphql/unauthorized_error"
autoload :UnauthorizedEnumValueError, "graphql/unauthorized_enum_value_error"
autoload :UnauthorizedFieldError, "graphql/unauthorized_field_error"
Expand Down
4 changes: 2 additions & 2 deletions lib/graphql/execution.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# frozen_string_literal: true
require "graphql/execution/directive_checks"
require "graphql/execution/next"
require "graphql/execution/interpreter"
require "graphql/execution/lazy"
require "graphql/execution/lookahead"
require "graphql/execution/multiplex"
require "graphql/execution/next"
require "graphql/execution/errors"

module GraphQL
Expand All @@ -14,7 +14,7 @@ class Skip < GraphQL::RuntimeError
attr_accessor :path
def ast_nodes=(_ignored); end

def assign_graphql_result(query, result_data, key)
def finalize_graphql_result(query, result_data, key)
result_data.delete(key)
end
end
Expand Down
6 changes: 6 additions & 0 deletions lib/graphql/execution/interpreter/handles_raw_value.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ module Execution
class Interpreter
# Wrapper for raw values
class RawValue
include GraphQL::Execution::Next::Finalizer

def finalize_graphql_result(query, result_data, result_key)
result_data[result_key] = @object
end

def initialize(obj = nil)
@object = obj
end
Expand Down
7 changes: 7 additions & 0 deletions lib/graphql/execution/next.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,13 @@ def self.run_all(schema, query_options, context: {}, max_complexity: schema.max_
runner = Runner.new(multiplex, **schema.execution_next_options)
runner.execute
end

module Finalizer
attr_accessor :path
def finalize_graphql_result(query, result_data, result_key)
raise RequiredImplementationMissingError
end
end
end
end
end
62 changes: 46 additions & 16 deletions lib/graphql/execution/next/field_resolve_step.rb
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ def coerce_argument_value(arguments, arg_defn, arg_value, run_loads, target_keyw
end
end

if arg_value.is_a?(GraphQL::Error)
if arg_value.is_a?(GraphQL::RuntimeError)
@arguments = arg_value
elsif run_loads && arg_defn.loads && as_type.nil? && !arg_value.nil?
# This is for legacy compat:
Expand Down Expand Up @@ -292,7 +292,7 @@ def build_arguments
def execute_field
objects = @selections_step.objects
# TODO not as good because only one error?
if @arguments.is_a?(GraphQL::Error)
if @arguments.is_a?(GraphQL::RuntimeError)
@field_results = Array.new(objects.size, @arguments)
@object_is_authorized = AlwaysAuthorized
build_results
Expand Down Expand Up @@ -368,6 +368,37 @@ def execute_field
end

query.current_trace.begin_execute_field(@field_definition, @arguments, authorized_objects, query)

if @runner.uses_runtime_directives
if @ast_nodes.nil? || @ast_nodes.size == 1
directives = if @ast_node.directives.any?
@ast_node.directives
else
nil
end
else
directives = nil
@ast_nodes.each do |n|
if (d = n.directives).any? # rubocop:disable Development/NoneWithoutBlockCop
directives ||= []
directives.concat(d)
end
end
end

if directives
directives.each do |dir_node|
if (dir_defn = @runner.runtime_directives[dir_node.name])
# Skip or include won't be present
result = dir_defn.resolve_field(ast_nodes, @parent_type, field_definition, authorized_objects, @arguments, ctx)
if result.is_a?(Finalizer)
result.path = path
end
end
end
end
end

has_extensions = @field_definition.extensions.size > 0
if has_extensions
@extended = GraphQL::Schema::Field::ExtendedState.new(@arguments, authorized_objects)
Expand Down Expand Up @@ -520,8 +551,12 @@ def build_results
else
nil
end
elsif field_result.is_a?(GraphQL::Error)
add_graphql_error(field_result)
elsif field_result.is_a?(Finalizer)
if field_result.is_a?(GraphQL::RuntimeError)
add_graphql_error(field_result)
else
field_result.path = path
end
else
# TODO `nil`s in [T!] types aren't handled
return_type.coerce_result(field_result, ctx)
Expand Down Expand Up @@ -596,8 +631,13 @@ def build_graphql_result(graphql_result, key, field_result, return_type, is_nn,
else
graphql_result[key] = nil
end
elsif field_result.is_a?(GraphQL::Error)
graphql_result[key] = add_graphql_error(field_result)
elsif field_result.is_a?(Finalizer)
graphql_result[key] = if field_result.is_a?(GraphQL::RuntimeError)
add_graphql_error(field_result)
else
field_result.path = path
field_result
end
elsif is_list
if is_nn
return_type = return_type.of_type
Expand Down Expand Up @@ -728,16 +768,6 @@ def resolve_batch(objects, context, args_hash)
end
end
end

class RawValueFieldResolveStep < FieldResolveStep
def build_graphql_result(graphql_result, key, field_result, return_type, is_nn, is_list, is_from_array) # rubocop:disable Metrics/ParameterLists
if field_result.is_a?(Interpreter::RawValue)
graphql_result[key] = field_result.resolve
else
super
end
end
end
end
end
end
2 changes: 1 addition & 1 deletion lib/graphql/execution/next/load_argument_step.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def call
private

def assign_value
if @loaded_value.is_a?(GraphQL::Error)
if @loaded_value.is_a?(GraphQL::RuntimeError)
@loaded_value.path = @field_resolve_step.path
@field_resolve_step.arguments = @loaded_value
else
Expand Down
2 changes: 1 addition & 1 deletion lib/graphql/execution/next/prepare_object_step.rb
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def create_result
else
@graphql_result[@key] = @field_resolve_step.add_graphql_error(@authorization_error)
end
rescue GraphQL::Error => err
rescue GraphQL::RuntimeError => err
if @is_non_null
@graphql_result[@key] = @field_resolve_step.add_non_null_error(@is_from_array)
else
Expand Down
Loading
Loading