Skip to content
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

Merged
merged 3 commits into from
Nov 7, 2023

Conversation

nicoco007
Copy link
Contributor

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 scalar MyScalarType that inherits from GraphQL::Schema::Scalar and has a coerce_input that returns MyScalar, Tapioca will wrongly use MyScalarType 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.

@nicoco007 nicoco007 requested a review from a team as a code owner September 18, 2023 17:45
@nicoco007 nicoco007 requested review from Morriar and st0012 September 18, 2023 17:45
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"
Copy link
Contributor Author

@nicoco007 nicoco007 Sep 18, 2023

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!

Copy link
Member

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

return_type = signature.return_type
return if return_type == T::Private::Types::Void || return_type == T::Private::Types::NotTyped

Copy link
Member

@paracycle paracycle Nov 7, 2023

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.

@Tiedye
Copy link

Tiedye commented Oct 26, 2023

@paracycle are you able to look at this?

Copy link
Member

@paracycle paracycle left a 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"
Copy link
Member

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

return_type = signature.return_type
return if return_type == T::Private::Types::Void || return_type == T::Private::Types::NotTyped

@nicoco007
Copy link
Contributor Author

Oh sorry I wasn't paying attention, thanks for the change! I hadn't thought of those cases.

@paracycle paracycle merged commit 692e486 into main Nov 7, 2023
29 checks passed
@paracycle paracycle deleted the support-custom-scalar-coerce-input branch November 7, 2023 19:25
@paracycle
Copy link
Member

Oh sorry I wasn't paying attention, thanks for the change! I hadn't thought of those cases.

All good, thanks for your contribution. 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants