-
Notifications
You must be signed in to change notification settings - Fork 132
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for custom GraphQL scalar coercion #1659
Conversation
when GraphQL::Schema::Scalar.singleton_class | ||
method = Runtime::Reflection.method_of(unwrapped_type, :coerce_input) | ||
signature = Runtime::Reflection.signature_of(method) | ||
signature&.return_type&.to_s || "T.untyped" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The default behaviour of Scalar
is to just return the raw value so I think it makes more sense to return T.untyped
by default here rather than the unwrapped_type
. Happy to discuss!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this makes sense to me. However, this needs more finesse, since return_type
can be Void
or NotTyped
, neither of which make sense as a parameter type.
We need to do something similar to
tapioca/lib/tapioca/dsl/helpers/active_record_column_type_helper.rb
Lines 124 to 125 in 9c9b0e7
return_type = signature.return_type | |
return if return_type == T::Private::Types::Void || return_type == T::Private::Types::NotTyped |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I added this check and associated test cases in a commit, and will merge when the CI is green.
@paracycle are you able to look at this? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally this looks good to me but there is one aspect that needs improvement.
when GraphQL::Schema::Scalar.singleton_class | ||
method = Runtime::Reflection.method_of(unwrapped_type, :coerce_input) | ||
signature = Runtime::Reflection.signature_of(method) | ||
signature&.return_type&.to_s || "T.untyped" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this makes sense to me. However, this needs more finesse, since return_type
can be Void
or NotTyped
, neither of which make sense as a parameter type.
We need to do something similar to
tapioca/lib/tapioca/dsl/helpers/active_record_column_type_helper.rb
Lines 124 to 125 in 9c9b0e7
return_type = signature.return_type | |
return if return_type == T::Private::Types::Void || return_type == T::Private::Types::NotTyped |
Oh sorry I wasn't paying attention, thanks for the change! I hadn't thought of those cases. |
All good, thanks for your contribution. 🙏 |
Motivation
When trying to update our project to Tapioca v0.11.9, I ran into an issue with our custom scalars: Tapioca currently uses the GraphQL scalar class as the return type even if it defines a
coerce_input
method with a different return type. For example, if I have a scalarMyScalarType
that inherits fromGraphQL::Schema::Scalar
and has acoerce_input
that returnsMyScalar
, Tapioca will wrongly useMyScalarType
in generated signatures for mutations and input objects. This is an attempt at fixing that issue.I also shoehorned
GraphQL::Types::BigInt
here since I noticed it wasn't working properly either. Happy to separate that into its own PR if needed.Implementation
The approach I took is to simply check if a type signature exists on
coerce_input
and use the return type if it does. If not, it falls back to the current behaviour.Tests
I've added a test here and also checked against our project to make sure I didn't miss anything.