Skip to content

Commit b0738a0

Browse files
authored
Merge pull request #4902 from rmosolgo/fix-field-usage-on-prepared-input-types-with-original-value
Fix field usage on prepared input types with original value
2 parents ec1ae00 + 7fc0a5d commit b0738a0

File tree

7 files changed

+62
-8
lines changed

7 files changed

+62
-8
lines changed

lib/graphql/analysis/ast/field_usage.rb

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,26 +41,28 @@ def extract_deprecated_arguments(argument_values)
4141
@used_deprecated_arguments << argument.definition.path
4242
end
4343

44-
next if argument.value.nil?
44+
arg_val = argument.value
45+
46+
next if arg_val.nil?
4547

4648
argument_type = argument.definition.type
4749
if argument_type.non_null?
4850
argument_type = argument_type.of_type
4951
end
5052

5153
if argument_type.kind.input_object?
52-
extract_deprecated_arguments(argument.value.arguments.argument_values) # rubocop:disable Development/ContextIsPassedCop -- runtime args instance
54+
extract_deprecated_arguments(argument.original_value.arguments.argument_values) # rubocop:disable Development/ContextIsPassedCop -- runtime args instance
5355
elsif argument_type.kind.enum?
54-
extract_deprecated_enum_value(argument_type, argument.value)
56+
extract_deprecated_enum_value(argument_type, arg_val)
5557
elsif argument_type.list?
5658
inner_type = argument_type.unwrap
5759
case inner_type.kind
5860
when TypeKinds::INPUT_OBJECT
59-
argument.value.each do |value|
61+
argument.original_value.each do |value|
6062
extract_deprecated_arguments(value.arguments.argument_values) # rubocop:disable Development/ContextIsPassedCop -- runtime args instance
6163
end
6264
when TypeKinds::ENUM
63-
argument.value.each do |value|
65+
arg_val.each do |value|
6466
extract_deprecated_enum_value(inner_type, value)
6567
end
6668
else

lib/graphql/execution/interpreter/argument_value.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,19 @@ class Interpreter
66
# A container for metadata regarding arguments present in a GraphQL query.
77
# @see Interpreter::Arguments#argument_values for a hash of these objects.
88
class ArgumentValue
9-
def initialize(definition:, value:, default_used:)
9+
def initialize(definition:, value:, original_value:, default_used:)
1010
@definition = definition
1111
@value = value
12+
@original_value = original_value
1213
@default_used = default_used
1314
end
1415

1516
# @return [Object] The Ruby-ready value for this Argument
1617
attr_reader :value
1718

19+
# @return [Object] The value of this argument _before_ `prepare` is applied.
20+
attr_reader :original_value
21+
1822
# @return [GraphQL::Schema::Argument] The definition instance for this argument
1923
attr_reader :definition
2024

lib/graphql/schema/argument.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ def coerce_into_values(parent_object, values, context, argument_values)
290290
# TODO code smell to access such a deeply-nested constant in a distant module
291291
argument_values[arg_key] = GraphQL::Execution::Interpreter::ArgumentValue.new(
292292
value: resolved_loaded_value,
293+
original_value: resolved_coerced_value,
293294
definition: self,
294295
default_used: default_used,
295296
)

lib/graphql/schema/input_object.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,7 @@ def coerce_input(value, ctx)
215215
if resolved_arguments.is_a?(GraphQL::Error)
216216
raise resolved_arguments
217217
else
218-
input_obj_instance = self.new(resolved_arguments, ruby_kwargs: resolved_arguments.keyword_arguments, context: ctx, defaults_used: nil)
219-
input_obj_instance.prepare
218+
self.new(resolved_arguments, ruby_kwargs: resolved_arguments.keyword_arguments, context: ctx, defaults_used: nil)
220219
end
221220
end
222221
end

spec/graphql/analysis/ast/field_usage_spec.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,17 @@
254254
end
255255
end
256256

257+
describe "mutation with deprecated arguments with prepared values" do
258+
let(:query_string) {%|
259+
mutation {
260+
pushValue(preparedTestInput: { deprecatedDate: "2020-10-10" })
261+
}
262+
|}
263+
264+
it "keeps track of nested deprecated arguments" do
265+
assert_equal ['PreparedDateInput.deprecatedDate'], result[:used_deprecated_arguments]
266+
end
267+
end
257268

258269
describe "when an argument prepare raises a GraphQL::ExecutionError" do
259270
class ArgumentErrorFieldUsageSchema < GraphQL::Schema

spec/graphql/schema/input_object_spec.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,17 @@ def prepare
353353
end
354354
end
355355

356+
class OnlyOnePrepareInputObject < GraphQL::Schema::InputObject
357+
argument :i, Int
358+
359+
attr_reader :prepared_count
360+
def prepare
361+
@prepared_count ||= 0
362+
@prepared_count += 1
363+
super
364+
end
365+
end
366+
356367
class SmallIntegerArgument < GraphQL::Schema::Argument
357368
def authorized?(obj, val, ctx)
358369
if val > 100
@@ -388,6 +399,14 @@ def inputs(input:)
388399
end
389400

390401
field :hash_input, resolver: HashInputResolver
402+
403+
field :prepare_once, Int do
404+
argument :input, OnlyOnePrepareInputObject
405+
end
406+
407+
def prepare_once(input:)
408+
input.prepared_count
409+
end
391410
end
392411

393412
class Schema < GraphQL::Schema
@@ -404,6 +423,11 @@ class Schema < GraphQL::Schema
404423
assert_equal "5..10", res["data"]["inputs"]
405424
end
406425

426+
it "only prepares once" do
427+
res = InputObjectPrepareObjectTest::Schema.execute("{ prepareOnce( input: { i: 1 } ) }")
428+
assert_equal 1, res["data"]["prepareOnce"]
429+
end
430+
407431
it "calls prepare on the input object (variable)" do
408432
query_str = <<-GRAPHQL
409433
query ($input: RangeInput!){ inputs(input: $input) }

spec/support/dummy/schema.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,18 @@ class DairyProductInput < BaseInputObject
265265
argument :old_source, String, required: false, deprecation_reason: "No longer supported"
266266
end
267267

268+
class PreparedDateInput < BaseInputObject
269+
description "Input with prepared value"
270+
argument :date, String, description: "date as a string", required: false
271+
argument :deprecated_date, String, description: "date as a string", required: false, deprecation_reason: "Use date"
272+
273+
def prepare
274+
return nil unless date || deprecated_date
275+
276+
Date.parse(date || deprecated_date)
277+
end
278+
end
279+
268280
class DeepNonNull < BaseObject
269281
field :non_null_int, Integer, null: false do
270282
argument :returning, Integer, required: false
@@ -492,6 +504,7 @@ class DairyAppMutation < BaseObject
492504
field :push_value, [Integer], null: false, description: "Push a value onto a global array :D" do
493505
argument :value, Integer, as: :val
494506
argument :deprecated_test_input, DairyProductInput, required: false
507+
argument :prepared_test_input, PreparedDateInput, required: false
495508
end
496509
def push_value(val:)
497510
GLOBAL_VALUES << val

0 commit comments

Comments
 (0)