Skip to content

Fix argument deserialization#2654

Closed
TomasBarry wants to merge 1 commit intormosolgo:masterfrom
TomasBarry:fix/argument-deserialization
Closed

Fix argument deserialization#2654
TomasBarry wants to merge 1 commit intormosolgo:masterfrom
TomasBarry:fix/argument-deserialization

Conversation

@TomasBarry
Copy link
Copy Markdown
Contributor

As outlined in #2611
there appears to be a bug in argument deserialization if the argument
contains a number. This bug was confirmed by @rmosolgo here

This commit contains a patch for the bug. The culprit was
GraphQL::Schema::Member::BuildType#underscore. Upon investigation,
this method used gsub to include underscores but just split the string
based on letters. This was confirmed by adding a test for the
#underscore method in spec/graphql/schema/member/build_type_spec.rb
which was not initially present.

After identifying the issue, the following two gsub calls were chained
to the underscore method:

.gsub(/([A-Za-z]+)([0-9]+)/,'\1_\2')  # some1 -> some_1
.gsub(/([0-9]+)([A-Za-z]+)/,'\1_\2')  # 1thing -> 1_thing

Having added the tests that confirm the bug has been fixed, a number of
other tests failed due to the test code using the incorrectly
deserialized values. This commit also patches these tests.

As outlined in rmosolgo#2611
there appears to be a bug in argument deserialization if the argument
contains a number. This bug was confirmed by @rmosolgo [here](rmosolgo#2611 (comment))

This commit contains a patch for the bug. The culprit was
`GraphQL::Schema::Member::BuildType#underscore`. Upon investigation,
this method used gsub` to include underscores but just split the string
based on letters. This was confirmed by adding a test for the
`#underscore` method in `spec/graphql/schema/member/build_type_spec.rb`
which was not initially present.

After identifying the issue, the following two `gsub` calls were chained
to the `underscore` method:

```ruby
.gsub(/([A-Za-z]+)([0-9]+)/,'\1_\2')  # some1 -> some_1
.gsub(/([0-9]+)([A-Za-z]+)/,'\1_\2')  # 1thing -> 1_thing
```

Having added the tests that confirm the bug has been fixed, a number of
other tests failed due to the test code using the incorrectly
deserialized values. This commit also patches these tests.
@TomasBarry
Copy link
Copy Markdown
Contributor Author

@rmosolgo, if this PR is fit for purpose, would you rather the extra files be submitted as patches in a set of other commits so that this commit just deals with the bug itself (I mean submitting the changes to spec/graphql/authorization_spec.rb, spec/graphql/execution/errors_spec.rb, spec/graphql/schema/input_object_spec.rb, and spec/graphql/schema/resolver_spec.rb)?

@rmosolgo
Copy link
Copy Markdown
Owner

Sorry for the slow response here. I'm a little bit wary of this change because it looks like it will change behavior for anyone using names like field1, is that right? I'm worried we'll trade one unexpected behavior for another.

Do you think it's possible to respect the case as written in the field name? That is, if someone writes field :f_1, then we use f_1, but if they write f2, we use f2?

@TomasBarry
Copy link
Copy Markdown
Contributor Author

I'm a little bit wary of this change because it looks like it will change behavior for anyone using names like field1, is that right? I'm worried we'll trade one unexpected behavior for another.

Yeah, that is the case which is why I'm not too keen on it either.

Do you think it's possible to respect the case as written in the field name? That is, if someone writes field :f_1, then we use f_1, but if they write f2, we use f2?

That's something that I'll have to look into. Any pointers on where to start looking for that?

@rmosolgo
Copy link
Copy Markdown
Owner

where to start

I think it basically requires a paradigm shift on how this works. Currently, the library assumes that:

  • Ruby fields use underscored names;
  • AND GraphQL fields use camelized name;
  • THEREFORE a camelize(...) or underscore(...) transformation can be used to translate between Ruby and GraphQL.

However, the issue you outlined over in #2611 demonstrates a flaw in this approach: we have differing expectations about how the transform should work -- or at least, the way it previously worked was wrong.

So, I think a better approach to this feature would be:

  • Ruby fields are given names using field(name, ...) configurations;
  • AND GraphQL names are generated during that configuration (often with camelize: true, but not necessarily so)
  • THEREFORE the configured GraphQL::Schema::Field instance should be used to map GraphQL and Ruby names for different fields

In an approach like that, camelize(...) is used only to generate a GraphQL name for the field. After that, no transform is used. Instead, the field objects themselves are used to match a GraphQL name to a Ruby name.

I'm not exactly sure what will be required to implement that, but I think you could basically start by:

  • Looking for places where underscore(...) is used to transform field names, then
  • Finding a way to replace that transformation with a lookup of the name used in the configuration

But, I'm not exactly sure how that will play out 🙈 !

@rmosolgo
Copy link
Copy Markdown
Owner

rmosolgo commented Mar 2, 2020

I took a different approach in #2792 which maintained the current behavior, too. Please give it a try on master or 1.10.4 which will be released soon, and let me know if you run into any trouble!

@rmosolgo rmosolgo closed this Mar 2, 2020
@TomasBarry TomasBarry deleted the fix/argument-deserialization branch March 2, 2020 17:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants