Comments (3)
Hey, thanks for reporting this and sorry for the trouble. I don't know of a better fix than the guideline-tech#1, because as you noticed, the un-prepared value isn't available.
It might be possible to add an original_value
method to ArgumentValue
. We could retain a reference to it from these two places that prepare_value
is called:
graphql-ruby/lib/graphql/schema/input_object.rb
Lines 29 to 34 in 1c4b1dc
graphql-ruby/lib/graphql/schema/argument.rb
Lines 274 to 279 in 1c4b1dc
from graphql-ruby.
Hello, I probably misunderstood what you meant here, but when I tried getting the value from prepare_value
it seems the value was already prepared ( converted to the Date
) and I was not able to use it as an argument, were you thinking of using the Hash
value as original_value
and convert it to ArgumentValue
in FieldUsage
?
Otherwise the value is already prepared as Date
from
graphql-ruby/lib/graphql/schema/input_object.rb
Lines 218 to 219 in 66b5720
Which is called in
graphql-ruby/lib/graphql/schema/argument.rb
Lines 264 to 265 in 1c4b1dc
I was able to get it working, but the solution seems dirty, not sure if I should add a method to get the unprepared value from the raw not-coerced value.
diff --git a/lib/graphql/analysis/ast/field_usage.rb b/lib/graphql/analysis/ast/field_usage.rb
index dc83577dbd..185b9a8f9b 100644
--- a/lib/graphql/analysis/ast/field_usage.rb
+++ b/lib/graphql/analysis/ast/field_usage.rb
@@ -48,8 +48,8 @@ module GraphQL
argument_type = argument_type.of_type
end
- if argument_type.kind.input_object? && argument.value.respond_to?(:arguments) # Skip if value is not a GraphQL::Schema::InputObject
- extract_deprecated_arguments(argument.value.arguments.argument_values) # rubocop:disable Development/ContextIsPassedCop -- runtime args instance
+ if argument_type.kind.input_object?
+ extract_deprecated_arguments(argument.original_value.arguments.argument_values) # rubocop:disable Development/ContextIsPassedCop -- runtime args instance
elsif argument_type.kind.enum?
extract_deprecated_enum_value(argument_type, argument.value)
elsif argument_type.list?
diff --git a/lib/graphql/execution/interpreter/argument_value.rb b/lib/graphql/execution/interpreter/argument_value.rb
index 4ca37977c0..82d31f3804 100644
--- a/lib/graphql/execution/interpreter/argument_value.rb
+++ b/lib/graphql/execution/interpreter/argument_value.rb
@@ -6,15 +6,19 @@ module GraphQL
# A container for metadata regarding arguments present in a GraphQL query.
# @see Interpreter::Arguments#argument_values for a hash of these objects.
class ArgumentValue
- def initialize(definition:, value:, default_used:)
+ def initialize(definition:, value:, original_value:, default_used:)
@definition = definition
@value = value
+ @original_value = original_value
@default_used = default_used
end
# @return [Object] The Ruby-ready value for this Argument
attr_reader :value
+ # @return [Object] The original Ruby-ready value for this Argument
+ attr_reader :original_value
+
# @return [GraphQL::Schema::Argument] The definition instance for this argument
attr_reader :definition
diff --git a/lib/graphql/schema/argument.rb b/lib/graphql/schema/argument.rb
index 633f329b65..dfa85a69a2 100644
--- a/lib/graphql/schema/argument.rb
+++ b/lib/graphql/schema/argument.rb
@@ -261,8 +261,11 @@ module GraphQL
end
loaded_value = nil
+ original_value = nil
coerced_value = begin
- type.coerce_input(value, context)
+ type.coerce_input(value, context) do |input_obj_instance|
+ original_value = input_obj_instance
+ end
rescue StandardError => err
context.schema.handle_or_reraise(context, err)
end
@@ -290,6 +293,7 @@ module GraphQL
# TODO code smell to access such a deeply-nested constant in a distant module
argument_values[arg_key] = GraphQL::Execution::Interpreter::ArgumentValue.new(
value: resolved_loaded_value,
+ original_value: original_value,
definition: self,
default_used: default_used,
)
diff --git a/lib/graphql/schema/input_object.rb b/lib/graphql/schema/input_object.rb
index 46c69c1826..856eae5ef5 100644
--- a/lib/graphql/schema/input_object.rb
+++ b/lib/graphql/schema/input_object.rb
@@ -216,6 +216,7 @@ module GraphQL
raise resolved_arguments
else
input_obj_instance = self.new(resolved_arguments, ruby_kwargs: resolved_arguments.keyword_arguments, context: ctx, defaults_used: nil)
+ yield input_obj_instance if block_given?
input_obj_instance.prepare
end
end
diff --git a/spec/graphql/analysis/ast/field_usage_spec.rb b/spec/graphql/analysis/ast/field_usage_spec.rb
index 53cafb4851..56924b3904 100644
--- a/spec/graphql/analysis/ast/field_usage_spec.rb
+++ b/spec/graphql/analysis/ast/field_usage_spec.rb
@@ -254,18 +254,30 @@ describe GraphQL::Analysis::AST::FieldUsage do
end
end
- describe "mutation with deprecated arguments with prepared values does not break" do
+ describe "mutation with deprecated arguments with prepared values" do
let(:query_string) {%|
mutation {
- pushValue(preparedTestInput: { deprecatedDate: "2020-10-10" })
+ pushValue(preparedTestInput: { date: "2020-10-10" })
}
|}
- it "does not keeps track of nested deprecated arguments" do
+ it "does not return non-deprecated arguments" do
assert_equal [], result[:used_deprecated_arguments]
end
end
+ describe "mutation with deprecated arguments with prepared values" do
+ let(:query_string) {%|
+ mutation {
+ pushValue(preparedTestInput: { deprecatedDate: "2020-10-10" })
+ }
+ |}
+
+ it "keeps track of nested deprecated arguments" do
+ assert_equal ['PreparedDateInput.deprecatedDate'], result[:used_deprecated_arguments]
+ end
+ end
+
describe "when an argument prepare raises a GraphQL::ExecutionError" do
class ArgumentErrorFieldUsageSchema < GraphQL::Schema
class FieldUsage < GraphQL::Analysis::AST::FieldUsage
from graphql-ruby.
Hey! Sorry it took me a while to come back to this. Thanks for sharing what you found when you investigated that fix. I agree, it didn't turn out as nice as I thought it might...
I reviewed this part of the gem and noticed that input_object.prepare
was actually being called twice. First, when incoming GraphQL arguments are being turned into an InputObject instance:
graphql-ruby/lib/graphql/schema/input_object.rb
Lines 218 to 219 in ec1ae00
Then, later, the Argument code calls .prepare
again:
graphql-ruby/lib/graphql/schema/argument.rb
Lines 208 to 211 in ec1ae00
For normal uses of .prepare
, that second call would never happen because the value would no longer be an InputObject instance. But the default implementation of InputObject#prepare
is to return itself
, and in that case, it was being called twice.
I found that if I removed that first call to .prepare
, then it was much easier to capture original_value
and pass it along to the ArgumentValue
. I took that approach in #4902.
from graphql-ruby.
Related Issues (20)
- Add timestamp to subscription updates HOT 5
- Test files ship with graphql-pro and graphql-enterprise HOT 4
- Version 1.13.22 uninitialized constant error HOT 6
- ArgumentError: wrong number of arguments (given 6, expected 7) GraphQL v2.3.0 c_parser v1.0.7 HOT 1
- Possibility to generate GraphQL comments HOT 2
- Support Lazy Enumerators with Stream
- [How to] define one of two arguments required in a mutation HOT 1
- Support Arel::Nodes::NullsFirst in GraphQL::Pro::Order::RelationConnection::Order#normalize HOT 2
- Add option to use ordered relation for count HOT 6
- A way to apply some sort of default_scope for ONLY graphql queries/mutations HOT 3
- Private vulnerability reporting HOT 2
- Queries with multiline strings inputs are still failing even using the backported method HOT 5
- [PRO] Connection based query splitting HOT 3
- CamelCase vs snake_case (again) HOT 1
- Lazy resolvers HOT 3
- AsyncDataloader improvements for Rails
- Infinity not allowed in JSON raised when calling GraphQL::Query.new with inf values and using graphql pro operation store HOT 1
- Compatibility for run_graphql_field with lookahead extra HOT 1
- Unable to delete directive definition nodes using visitor HOT 1
- 2.3.1 changes previous mutation behaviour re optional arguments HOT 6
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from graphql-ruby.