How to format graphql query string

My graphql query string is very long and some of them are reused, so I want to separate them as strings. But I don't know how to assemble them.

Because the query string is too long, I temporarily use "..." to indicate it.

pub const USER: &'static str = r#"
  user{
    id
    ...
  }
"#;
pub const REPLY: &'static str = r#"
   replies{
     id
     ...
   }
"#;
pub const MEDIA: &'static str = r#"
   medias{
     id
     ...
   }
"#;

// I want to insert the above string into POST
// Assuming the form of {variable}
pub const POST: &'static str = r#"query(
  $id: String!
) {
  getPost(id: $id){ 
    id 
    text
    {USER}
    {REPLY}
    {MEDIA}   
    ...
    created_at
  }
}"#;

I don't know how to implement this features. I have tried format! and other methods, but they can't be implemented.

Compared with other languages, such as js, it is very simple to implement this features. E.g:

// es6 template string
let gql_query_str = `
  query(
    $id: String!
  ) {
    getPost(id: $id){ 
      id 
      text
      ${USER}
      ${REPLY}
      ${MEDIA}
      ...
      created_at
    }
  }
`

This took me a while to figure out too. Here's how I did it.

Thanks

I look forward to a better solution.

For something like this, I’d probably reach for build.rs. It can produce the final query strings as files using any templating system you find convenient, and then your source files can use include_bytes! to read them in as constants.

In a mixed-language project, I’d probably reach for something like m4 to do the compile-time string manipulations, instead of Rust. That pretty strongly makes it UNIX-only, though.

I made it complicated. I thought of a better way, I can use the replace method to do this, it's not difficult.

pub fn gql_query_str() -> String {
  String::from(r#"
    query(
      $id: String!
    ) {
      getPost(id: $id){ 
        id 
        text
        {USER}
        {REPLY}
        {MEDIA}   
        created_at
      }
    }
  "#)
    .replace("{USER}", USER)
    .replace("{REPLY}", REPLY)
    .replace("{MEDIA}", MEDIA)
}
1 Like