Skip to content

Unable to use inline fragment - Complex data-type #468

Open
@debanjanbasu

Description

@debanjanbasu

I'm trying to consume the enum from a complex query that involves inline fragments. However, I'm unable to get any of the fragments, neither the as, as mentioned in some documents. Any advice would be much appreciated 🙏.

#[derive(GraphQLQuery)] #[graphql( schema_path = "src/schemas/pluralsight_schema.graphql", query_path = "src/queries/pluralsight_queries.graphql", response_derives = "Debug, Serialize, Deserialize, PartialEq, Clone" )] struct ChannelContent;

query ChannelContent($channelId: String!) { channelContent(first: 1000, filter: { channelId: $channelId }) { nodes { id channelId index type __typename ... on Section { name description content { id index type __typename ... on ExternalLinkSection { url title contentType level durationInSeconds } } } __typename ... on ExternalLink { url title contentType level durationInSeconds } } } }

Any example or post would also do, on how to process these kind of complex queries.

Activity

tomhoule

tomhoule commented on Dec 21, 2023

@tomhoule
Member

What is missing from channel_content::ResponseData? There are tests using inline fragments, e.g.

fn type_refining_fragment_on_union() {

debanjanbasu

debanjanbasu commented on Dec 22, 2023

@debanjanbasu
Author

Thanks for getting back quickly @tomhoule, following is my code that's parsing the responsedata:

async fn get_channel_content(channel_id: &str) -> Result<Vec<ChannelContentChannelContentNodes>> {
    let response = post_graphql::<ChannelContent, _>(
        &get_reqwest_client().unwrap(),
        CONFIG.gql_endpoint,
        channel_content::Variables {
            channel_id: channel_id.to_string(),
        },
    )
    .await;
    // Extract nodes from the response parsing the Result response
    let nodes = response?
        .data
        .unwrap()
        .channel_content
        .nodes
        .unwrap()
        .into_iter()
        .map(|node| node.unwrap())
        .collect();
    Ok(nodes)
}

What's missing is this:

image

There should be something similar to onSection / onExternalLink right? Judging by the query:

query ChannelContent($channelId: String!) {
  channelContent(first: 1000, filter: { channelId: $channelId }) {
    nodes {
      id
      channelId
      index
      type
      __typename
      ... on Section {
        name
        description
        content {
          id
          index
          type
          __typename
          ... on ExternalLinkSection {
            url
            title
            contentType
            level
            durationInSeconds
          }
        }
      }
      __typename
      ... on ExternalLink {
        url
        title
        contentType
        level
        durationInSeconds
      }
    }
  }
}
tomhoule

tomhoule commented on Dec 26, 2023

@tomhoule
Member

I think the on is an enum, so you should be able to match node.on { ... }, and ChannelContentChannelContentNodesOn should have a variant like ChannelContentChannelContentNodesOn::ExternalLinkSection(...). I haven't worked on this library in a while, my memory may be wrong.

debanjanbasu

debanjanbasu commented on Dec 31, 2023

@debanjanbasu
Author

ChannelContentChannelContentNodesOn

Thanks and that does help. Probably I'm new to Rust and need a bit more of guidance on how to get the other key values from the Sections, and Section Contents 😅 🙏. Thanking in advance, and happy new year @tomhoule 🎉.

tomhoule

tomhoule commented on Jan 2, 2024

@tomhoule
Member

It gets a bit hard to read, but from the test I linked earlier, you can see there should be a nested struct inside the enum on on, so something like:

ChannelContentChannelContentNodesOn::ExternalLinkSection(ChannelContentChannelContentNodesOnExternalLinkSection { ... })

This library is hard to use if you don't look at the generated code (the CLI can help with that) or have a working IDE that can help you with completing type names.

Happy new year to you too :)

Christoph-AK

Christoph-AK commented on Feb 12, 2024

@Christoph-AK

Hey there! Man, this stuff is frustrating as the types are not correctly shown in vscode with rust analyzer half the time and check times get increasingly longer the more statements arer involved.

I try to make calls to shopify API with this query:

query QueryBulkOperation($id: ID!) {
  node(id:$id) {
    __typename
    ... on BulkOperation {
      status
      url
    }
  }
}

but cant figure out how to unpack the on BulkOperation conversion.

I tried to follow the examples in the test, but get Field 'on' not found in type query_bulk_operation::QueryBulkOperationNode.

#[derive(GraphQLQuery)]
#[graphql(
    schema_path = "src/gql/shopify-gql-schema.json",
    query_path = "src/gql/query-bulk-operation.graphql",
    response_derives = "Debug,PartialEq"
)]
pub struct QueryBulkOperation;

pub async fn gql_bulk_operation() {
   ... 
   
            // query bulk query status
            let q = QueryBulkOperation::build_query(query_bulk_operation::Variables {
                id: bulk_operation.id.clone(),
            });

            let response = client
                .post(format!(
                    "{}admin/api/{}/graphql.json",
                    &config.base_url, &config.api_version
                ))
                .json(&q)
                .send()
                .await?;

            if response.status() == StatusCode::OK {
                use query_bulk_operation::*;
                let response_body:
                    <QueryBulkOperation as graphql_client::GraphQLQuery>::ResponseData
                 = response.json().await?;
                let bulk_operation = response_body.node
                    .ok_or_eyre("No bulk_operation in response")?;

                match bulk_operation.on {
                   // ERROR: `Field 'on' not found in type query_bulk_operation::QueryBulkOperationNode`.
                }
           }
    }

How is this supposed to work?

Gumichocopengin8

Gumichocopengin8 commented on May 30, 2024

@Gumichocopengin8

I have the same issue @Christoph-AK has. When on is used, the code doesn't compile.
@tomhoule how can we fix this?

This is GitHub API.

# GitHub GraphQL API

query QueryProjectStatusField($projectId: ID!) {
  node(id: $projectId) {
    __typename
    ... on Projectv2 {
      field(name: "Status") {
        __typename
        ... on ProjectV2SingleSelectField {
          id
        }
      }
    }
  }
}
#[derive(GraphQLQuery)]
#[graphql(
    schema_path = "src/schema.json",
    query_path = "src/query.graphql",
    response_derives = "Debug, PartialEq, Eq"
)]
pub struct QueryProjectStatusField;

Thanks for the great library!

Christoph-AK

Christoph-AK commented on May 30, 2024

@Christoph-AK

@Gumichocopengin8 as workaround I am now serialising my 'on'-data with json. It's... not at all what this library is about, but at least that way my queries are working.

Gumichocopengin8

Gumichocopengin8 commented on May 30, 2024

@Gumichocopengin8

Thank you! I'll try that out.
Do you have a plan to fix this issue?

Gumichocopengin8

Gumichocopengin8 commented on May 30, 2024

@Gumichocopengin8

@tomhoule If I want to fix the issue, which code file should I take a look at?

Gumichocopengin8

Gumichocopengin8 commented on Jun 5, 2024

@Gumichocopengin8

@Christoph-AK Sorry for many comments.
I tried to accessing to on by serializing the data, but couldn't make it well. Could you please provide the code?
Thank you.

tomhoule

tomhoule commented on Jun 7, 2024

@tomhoule
Member

I'm not able to help here, sorry, it would take time to look at the generated code. If there is a bug, ideally we would have an issue with a straightforward reproduction, and someone can take a look at it. I am not able to spend time on this project at the moment.

Christoph-AK

Christoph-AK commented on Jun 8, 2024

@Christoph-AK

@Gumichocopengin8 Only just found some time to answer, sorry.

I'm not contributing, so I can't really give you pointers on how to solve this within the crate, but my solution for a Shopify gql batch call is like this:

query QueryBulkOperation($id: ID!) {
  node(id:$id) {
    __typename
    ... on BulkOperation {
      id
      status
      errorCode
    }
  }
}
#[derive(GraphQLQuery)]
#[graphql(
    schema_path = "src/gql/shopify-gql-schema.json",
    query_path = "src/gql/query-bulk-operation.graphql",
    response_derives = "Debug,PartialEq"
)]
pub struct QueryBulkOperation;

    // register bulk query and get id    
    // ...

          let q = QueryBulkOperation::build_query(query_bulk_operation::Variables {
              id: bulk_operation.id.clone(),
          });

          let response = client
              .post(format!(
                  "{}admin/api/{}/graphql.json",
                  &config.base_url, &config.api_version
              ))
              .json(&q)
              .send()
              .await?;

          let status = response.status();
          let text = response.text().await?;

          if status == StatusCode::OK {
              // deserialise text into generic json object

              let v: Value = serde_json::from_str(&text)?; 

              // the 'on' complication gets completely ignored in the conversion.
              // just access the fields directly, if you are certain what fields to expect. 
              // otherwise match on the typename. 

              let status = v["data"]["node"]["status"].as_str(); 

              debug!(
                  "GQL Query Bulk Operation Status: id: {}, status: {status:?}",
                  bulk_operation.id
              );

              if status == Some("COMPLETED") {
                // ....
              }
           }

Hope this helps!

Gumichocopengin8

Gumichocopengin8 commented on Jun 8, 2024

@Gumichocopengin8

I'm not able to help here, sorry, it would take time to look at the generated code. If there is a bug, ideally we would have an issue with a straightforward reproduction, and someone can take a look at it. I am not able to spend time on this project at the moment.

if I can make a easy reproduction code, I'll make one as a new issue with the code.

Gumichocopengin8

Gumichocopengin8 commented on Jun 8, 2024

@Gumichocopengin8

@Christoph-AK thanks! that's really helpful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @debanjanbasu@tomhoule@Gumichocopengin8@Christoph-AK

        Issue actions

          Unable to use inline fragment - Complex data-type · Issue #468 · graphql-rust/graphql-client