Skip to content

Commit

Permalink
Merge pull request #4128 from rmosolgo/prepare-before-loads
Browse files Browse the repository at this point in the history
Call prepare before loads for all arguments
  • Loading branch information
rmosolgo committed Jul 4, 2022
2 parents 2a4824d + 7c980cb commit d1b9212
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 11 deletions.
20 changes: 10 additions & 10 deletions lib/graphql/schema/argument.rb
Expand Up @@ -259,26 +259,26 @@ def coerce_into_values(parent_object, values, context, argument_values)
# If this isn't lazy, then the block returns eagerly and assigns the result here
# If it _is_ lazy, then we write the lazy to the hash, then update it later
argument_values[arg_key] = context.schema.after_lazy(coerced_value) do |resolved_coerced_value|
owner.validate_directive_argument(self, resolved_coerced_value)
prepared_value = begin
prepare_value(parent_object, resolved_coerced_value, context: context)
rescue StandardError => err
context.schema.handle_or_reraise(context, err)
end

if loads && !from_resolver?
loaded_value = begin
load_and_authorize_value(owner, coerced_value, context)
load_and_authorize_value(owner, prepared_value, context)
rescue StandardError => err
context.schema.handle_or_reraise(context, err)
end
end

maybe_loaded_value = loaded_value || resolved_coerced_value
maybe_loaded_value = loaded_value || prepared_value
context.schema.after_lazy(maybe_loaded_value) do |resolved_loaded_value|
owner.validate_directive_argument(self, resolved_loaded_value)
prepared_value = begin
prepare_value(parent_object, resolved_loaded_value, context: context)
rescue StandardError => err
context.schema.handle_or_reraise(context, err)
end

# TODO code smell to access such a deeply-nested constant in a distant module
argument_values[arg_key] = GraphQL::Execution::Interpreter::ArgumentValue.new(
value: prepared_value,
value: resolved_loaded_value,
definition: self,
default_used: default_used,
)
Expand Down
48 changes: 47 additions & 1 deletion spec/graphql/schema/input_object_spec.rb
Expand Up @@ -126,6 +126,24 @@ def prep(val)
end
end

class Thing < GraphQL::Schema::Object
field :name, String
end

class PreparedInputObj < GraphQL::Schema::InputObject
argument :thing_id, ID, loads: Thing, prepare: ->(val, ctx) { "thing-#{val}" }
end

class ResolverPrepares < GraphQL::Schema::Resolver
argument :input_object, PreparedInputObj
argument :thing_id, ID, loads: Thing, prepare: ->(val, ctx) { "thing-#{val}" }
type [String], null: false

def resolve(thing:, input_object:)
[thing.name, input_object[:thing].name]
end
end

class Query < GraphQL::Schema::Object
field :inputs, [String], null: false do
argument :input, InputObj
Expand All @@ -134,6 +152,20 @@ class Query < GraphQL::Schema::Object
def inputs(input:)
[input.to_kwargs.inspect, input.instrument.name]
end

field :multiple_prepares, [String] do
argument :input_object, PreparedInputObj
argument :thing_id, ID, loads: Thing, prepare: ->(val, ctx) { "thing-#{val}" }
end

def multiple_prepares(thing:, input_object:)
[thing.name, input_object[:thing].name]
end

field :resolver_prepares, resolver: ResolverPrepares


field :t, Thing
end

class Mutation < GraphQL::Schema::Object
Expand Down Expand Up @@ -193,7 +225,13 @@ class Schema < GraphQL::Schema
lazy_resolve(Proc, :call)

def self.object_from_id(id, ctx)
-> { Jazz::GloballyIdentifiableType.find(id) }
-> {
if id.start_with?("thing-")
OpenStruct.new(name: id)
else
Jazz::GloballyIdentifiableType.find(id)
end
}
end

def self.resolve_type(type, obj, ctx)
Expand All @@ -205,6 +243,14 @@ def self.resolve_type(type, obj, ctx)
end
end

it "always prepares before loading" do
res = InputObjectPrepareTest::Schema.execute("{ resolverPrepares(thingId: \"abc\", inputObject: { thingId: \"def\" }) }")
assert_equal ["thing-abc", "thing-def"], res["data"]["resolverPrepares"]

res = InputObjectPrepareTest::Schema.execute("{ multiplePrepares(thingId: \"abc\", inputObject: { thingId: \"def\" }) }")
assert_equal ["thing-abc", "thing-def"], res["data"]["multiplePrepares"]
end

it "calls methods on the input object" do
query_str = <<-GRAPHQL
{ inputs(input: { a: 1, b: 2, c: 3, d: 4, e: 5, instrumentId: "Instrument/Drum Kit" }) }
Expand Down

0 comments on commit d1b9212

Please sign in to comment.