Skip to content

Commit ff89261

Browse files
committed
Add full doctest example for the GraphQLQuery trait
1 parent 80d189b commit ff89261

File tree

7 files changed

+66
-7
lines changed

7 files changed

+66
-7
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
1111

1212
- Implemented support for the `extensions` field on errors from the June 2018 spec (#64).
1313

14+
### Fixed
15+
16+
- `Location` fields on errors were not public.
17+
- The field names on input objects were not properly converted between snake and camel case.
18+
1419

1520
### Changed
1621

graphql_query_derive/src/inputs.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use failure;
22
use graphql_parser;
3+
use heck::SnakeCase;
34
use introspection_response;
45
use objects::GqlObjectField;
56
use proc_macro2::{Ident, Span, TokenStream};
@@ -21,7 +22,7 @@ impl GqlInput {
2122
fields.sort_unstable_by(|a, b| a.name.cmp(&b.name));
2223
let fields = fields.iter().map(|field| {
2324
let ty = field.type_.to_rust(&context, "");
24-
let name = Ident::new(&field.name, Span::call_site());
25+
let name = Ident::new(&field.name.to_snake_case(), Span::call_site());
2526
quote!(pub #name: #ty)
2627
});
2728

@@ -136,7 +137,7 @@ mod tests {
136137
"# [ serde ( rename_all = \"camelCase\" ) ] ",
137138
"pub struct Cat { ",
138139
"pub offsprings : Vec < Cat > , ",
139-
"pub pawsCount : Float , ",
140+
"pub paws_count : Float , ",
140141
"pub requirements : Option < CatRequirements > , ",
141142
"}",
142143
].into_iter()

graphql_query_derive/src/query.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use failure;
22
use fragments::GqlFragment;
33
use graphql_parser;
4+
use heck::SnakeCase;
45
use proc_macro2::{Ident, Span, TokenStream};
56
use schema::Schema;
67
use selection::Selection;
@@ -43,7 +44,7 @@ impl QueryContext {
4344
let fields = self.variables.iter().map(|variable| {
4445
let name = &variable.name;
4546
let ty = variable.ty.to_rust(self, "");
46-
let name = Ident::new(name, Span::call_site());
47+
let name = Ident::new(&name.to_snake_case(), Span::call_site());
4748
quote!(pub #name: #ty)
4849
});
4950

@@ -54,6 +55,7 @@ impl QueryContext {
5455

5556
quote! {
5657
#[derive(Serialize)]
58+
#[serde(rename_all = "camelCase")]
5759
pub struct Variables {
5860
#(#fields,)*
5961
}

graphql_query_derive/src/schema.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ mod tests {
477477

478478
#[test]
479479
fn build_schema_works() {
480-
let gql_schema = include_str!("star_wars_schema.graphql");
480+
let gql_schema = include_str!("tests/star_wars_schema.graphql");
481481
let gql_schema = graphql_parser::parse_schema(gql_schema).unwrap();
482482
let built = Schema::from(gql_schema);
483483
assert_eq!(
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
query StarWarsQuery($episodeForHero: Episode!) {
2+
hero(episode: $episodeForHero) {
3+
name
4+
__typename
5+
}
6+
}

src/lib.rs

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! The top-level documentation resides on the [project README](https://github.com/tomhoule/graphql-client) at the moment.
22
//!
3-
//! The main interface to this library is the custom derive that generates modules from a GraphQL query and schema.
3+
//! The main interface to this library is the custom derive that generates modules from a GraphQL query and schema. See the docs for the [`GraphQLQuery`] trait for a full example.
44
55
#![deny(missing_docs)]
66

@@ -20,7 +20,52 @@ use std::collections::HashMap;
2020

2121
/// A convenience trait that can be used to build a GraphQL request body.
2222
///
23-
/// This will be implemented for you by codegen in the normal case.
23+
/// This will be implemented for you by codegen in the normal case. It is implemented on the struct you place the derive on.
24+
///
25+
/// Example:
26+
///
27+
///
28+
/// ```
29+
/// extern crate failure;
30+
/// #[macro_use]
31+
/// extern crate graphql_client;
32+
/// #[macro_use]
33+
/// extern crate serde_derive;
34+
/// #[macro_use]
35+
/// extern crate serde_json;
36+
/// extern crate serde;
37+
///
38+
/// #[derive(GraphQLQuery)]
39+
/// #[graphql(
40+
/// query_path = "graphql_query_derive/src/tests/star_wars_query.graphql",
41+
/// schema_path = "graphql_query_derive/src/tests/star_wars_schema.graphql"
42+
/// )]
43+
/// struct StarWarsQuery;
44+
///
45+
/// fn main() -> Result<(), failure::Error> {
46+
/// use graphql_client::GraphQLQuery;
47+
///
48+
/// let variables = star_wars_query::Variables {
49+
/// episode_for_hero: star_wars_query::Episode::NEWHOPE,
50+
/// };
51+
///
52+
/// let expected_body = json!({
53+
/// "query": star_wars_query::QUERY,
54+
/// "variables": {
55+
/// "episodeForHero": "NEWHOPE"
56+
/// },
57+
/// });
58+
///
59+
/// let actual_body = serde_json::to_value(
60+
/// StarWarsQuery::build_query(variables)
61+
/// )?;
62+
///
63+
/// assert_eq!(actual_body, expected_body);
64+
///
65+
/// Ok(())
66+
/// }
67+
/// ```
68+
/// ```
2469
pub trait GraphQLQuery<'de> {
2570
/// The shape of the variables expected by the query. This should be a generated struct most of the time.
2671
type Variables: serde::Serialize;
@@ -31,7 +76,7 @@ pub trait GraphQLQuery<'de> {
3176
fn build_query(variables: Self::Variables) -> GraphQLQueryBody<Self::Variables>;
3277
}
3378

34-
/// The form in which queries are sent over HTTP in most implemnetations.
79+
/// The form in which queries are sent over HTTP in most implementations. This will be built using the [`GraphQLQuery`] trait normally.
3580
#[derive(Debug, Serialize, Deserialize)]
3681
pub struct GraphQLQueryBody<Variables>
3782
where

0 commit comments

Comments
 (0)