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

Lookahead#selects? not matching fragment/type fields #3007

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

RobinDaugherty
Copy link
Contributor

There seems to be an issue with fields that are selected through fragments or types of a field. While the selections method returns the expected list of field names, calling selects? does not return true.

For example (extracted from a spec) I need know if the name field was requested on either the BirdSpecies or BirdGenus type.

query = GraphQL::Query.new(LookaheadTest::Schema, <<-GRAPHQL)
  query {
    node(id: "Cardinal") {
      ... on BirdSpecies {
        name
      }
      ... on BirdGenus {
        name
      }
      id
    }
  }
GRAPHQL

node_lookahead = query.lookahead.selection("node")

node_lookahead.selections.map(&:name)
=> [:id, :name, :name]

node_lookahead.selects?('id')
=> true

node_lookahead.selects?('name')
=> false

node_lookahead.selects?('BirdSpecies.name')
=> false

node_lookahead.selects?('birdSpecies.name')
=> false

I've added specs for Lookahead#selects? to demonstrate this. Am I correct that this is a bug, or am I misusing the selects? method?

@RobinDaugherty RobinDaugherty force-pushed the fix/lookahead-select-for-fragment-field branch from 73e41a7 to fdbd505 Compare June 28, 2020 17:28
while also adding a description of `#selects?` and moving some assertions from `#selections`
@RobinDaugherty RobinDaugherty force-pushed the fix/lookahead-select-for-fragment-field branch from fdbd505 to 7597939 Compare June 28, 2020 17:36
@RobinDaugherty RobinDaugherty changed the title Lookahead on fragment fields not giving correct results for selects? Lookahead#selects? not matching on fragment/type fields Jun 28, 2020
@RobinDaugherty RobinDaugherty changed the title Lookahead#selects? not matching on fragment/type fields Lookahead#selects? not matching fragment/type fields Jun 28, 2020
@rmosolgo
Copy link
Owner

Hey, yes, you've understood correctly, it's a bug! Do you want to take a crack at fixing it in this PR?

@timward60
Copy link

timward60 commented Jul 9, 2020

I believe this is because the way selection is implemented (which is called by selects?):
def selection(field_name, selected_type: @selected_type, arguments: nil)

selected_type is used to find the corresponding field selections. In the case of queries above the selected_type will be "Node". You can get the behavior desired above via:

node_lookahead.selection(:name, selected_type: schema.find_type("BirdGenus")).selected?
node_lookahead.selection(:name, selected_type: schema.find_type("BirdSpecies")).selected?

@gsdean
Copy link

gsdean commented Oct 1, 2020

Coming from here: https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache#limitations

Is there a proposed solution? We'd be willing to work on a PR, but not exactly sure where to start

@rmosolgo
Copy link
Owner

rmosolgo commented Oct 1, 2020

Hey @gsdean , this branch contains example tests but not a fix. Yes, if you want to open a PR with a fix, that'd be great!

@rmosolgo
Copy link
Owner

I blew the dust off these tests and got them passing, but I'm not sure it's the right implementation.

After my changes, a Lookahead has a map of { type => ast_nodes, ... }, to handle things like name in the example above. As a result, there's not just one field for a lookahead, but n fields, since, in the example of name above, there are two different name fields involved. But for compatibility, it still pretends to be a single-typed object, with field and owner_type methods. However, these methods misbehave for multi-typed Lookaheads. I could:

  • Leave it the way it is, and it would silently fail for code that encounters a multi-type situation;
  • Remove the single-type methods (#field, #owner_type) and force callers to update to the new methods
  • In between: raise when a lookahead has multiple types but a single-type method is called. In that case, the schema's code should be updated to use plural methods instead.

But they all seem complicated 😖

@jeromedalbert
Copy link

jeromedalbert commented Aug 19, 2021

I'm also coming from https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache#limitations. I am using that gem to facilitate caching, but because my schema has unions, some parts of my app can't be cached at the moment.

  • Leave it the way it is, and it would silently fail for code that encounters a multi-type situation;
  • Remove the single-type methods (#field, #owner_type) and force callers to update to the new methods
  • In between: raise when a lookahead has multiple types but a single-type method is called. In that case, the schema's code should be updated to use plural methods instead.

I'm guessing point 2 or 3 would be better than 1, because with solution 1 the graphql-ruby-fragment_cache gem would still not work with unions.

@jeromedalbert
Copy link

jeromedalbert commented Aug 10, 2023

@gsdean FYI I worked around the issue in my app by not using union types, and using interfaces instead. It seemed to mostly work.

Unions and interfaces in GraphQL are very similar, so migrating required minimal effort. No changes were needed for the frontend / API consumer, since the ... on syntax in queries remained the same.

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.

None yet

5 participants