@@ -3,20 +3,28 @@ use query::QueryContext;
3
3
use std:: collections:: BTreeSet ;
4
4
use selection:: { Selection , SelectionItem } ;
5
5
use heck:: SnakeCase ;
6
+ use failure;
6
7
7
8
#[ derive( Debug , PartialEq ) ]
8
9
pub struct GqlUnion ( pub BTreeSet < String > ) ;
9
10
11
+ #[ derive( Debug , Fail ) ]
12
+ #[ fail( display = "UnionError" ) ]
13
+ enum UnionError {
14
+ #[ fail( display = "Unknown type: {}" , ty) ]
15
+ UnknownType { ty : String } ,
16
+ }
17
+
10
18
impl GqlUnion {
11
19
pub fn response_for_selection (
12
20
& self ,
13
21
query_context : & QueryContext ,
14
22
selection : & Selection ,
15
23
prefix : & str ,
16
- ) -> TokenStream {
24
+ ) -> Result < TokenStream , failure :: Error > {
17
25
let struct_name = Ident :: new ( prefix, Span :: call_site ( ) ) ;
18
- let mut children_definitions = Vec :: new ( ) ;
19
- let fields = selection. 0 . iter ( ) . map ( |item| {
26
+ let mut children_definitions: Vec < TokenStream > = Vec :: new ( ) ;
27
+ let fields: Result < Vec < TokenStream > , failure :: Error > = selection. 0 . iter ( ) . map ( |item| {
20
28
match item {
21
29
SelectionItem :: Field ( _) => unreachable ! ( "field selection on union" ) ,
22
30
SelectionItem :: FragmentSpread ( _) => unreachable ! ( "fragment spread on union" ) ,
@@ -38,35 +46,123 @@ impl GqlUnion {
38
46
let field_union_type = query_context. schema . unions . get ( & frag. on )
39
47
. map ( |f| query_context. maybe_expand_field ( & frag. on , & frag. fields , & new_prefix) ) ;
40
48
41
- if let Some ( tokens) = field_object_type. or ( field_interface) . or ( field_union_type) {
42
- children_definitions. push ( tokens)
43
- }
49
+ match field_object_type. or ( field_interface) . or ( field_union_type) {
50
+ Some ( tokens) => children_definitions. push ( tokens?) ,
51
+ None => Err ( UnionError :: UnknownType { ty : frag. on . to_string ( ) } ) ?,
52
+ } ;
44
53
45
- // query_context.maybe_expand_field(
46
-
47
- // );
48
- quote ! {
54
+ Ok ( quote ! {
49
55
#field_name: #field_type
50
- }
56
+ } )
51
57
}
52
58
}
53
- } ) ;
59
+ } ) . collect ( ) ;
60
+
61
+ let fields = fields?;
62
+
63
+ Ok ( quote ! {
64
+ #( #children_definitions) *
54
65
55
- quote ! {
56
66
#[ derive( Deserialize ) ]
57
67
pub struct #struct_name {
58
68
#( #fields) , *
59
69
}
60
- }
70
+ } )
61
71
}
62
72
}
63
73
64
74
#[ cfg( test) ]
65
75
mod tests {
76
+ use selection:: * ;
77
+ use super :: * ;
78
+ use objects:: { GqlObject , GqlObjectField } ;
79
+ use field_type:: FieldType ;
66
80
67
81
#[ test]
68
82
fn union_response_for_selection_works ( ) {
69
- // unimplemented!()
70
- }
83
+ let fields = vec ! [
84
+ SelectionItem :: InlineFragment ( SelectionInlineFragment {
85
+ on: "User" . to_string( ) ,
86
+ fields: Selection ( vec![ SelectionItem :: Field ( SelectionField {
87
+ name: "first_name" . to_string( ) ,
88
+ fields: Selection ( vec![ ] ) ,
89
+ } ) ] ) ,
90
+ } ) ,
91
+ SelectionItem :: InlineFragment ( SelectionInlineFragment {
92
+ on: "Organization" . to_string( ) ,
93
+ fields: Selection ( vec![ SelectionItem :: Field ( SelectionField {
94
+ name: "title" . to_string( ) ,
95
+ fields: Selection ( vec![ ] ) ,
96
+ } ) ] ) ,
97
+ } ) ,
98
+ ] ;
99
+ let mut context = QueryContext :: new_empty ( ) ;
100
+ let selection = Selection ( fields) ;
101
+ let prefix = "Meow" ;
102
+ let union = GqlUnion ( BTreeSet :: new ( ) ) ;
103
+
104
+ let result = union. response_for_selection (
105
+ & context,
106
+ & selection,
107
+ & prefix,
108
+ ) ;
109
+
71
110
111
+ assert ! ( result. is_err( ) ) ;
112
+
113
+ context. schema . objects . insert (
114
+ "User" . to_string ( ) , GqlObject {
115
+ name : "User" . to_string ( ) ,
116
+ fields : vec ! [
117
+ GqlObjectField {
118
+ name: "first_name" . to_string( ) ,
119
+ type_: FieldType :: Named ( Ident :: new( "String" , Span :: call_site( ) ) ) ,
120
+ } ,
121
+ GqlObjectField {
122
+ name: "last_name" . to_string( ) ,
123
+ type_: FieldType :: Named ( Ident :: new( "String" , Span :: call_site( ) ) ) ,
124
+ } ,
125
+ GqlObjectField {
126
+ name: "created_at" . to_string( ) ,
127
+ type_: FieldType :: Named ( Ident :: new( "Date" , Span :: call_site( ) ) ) ,
128
+ }
129
+ ] ,
130
+ }
131
+ ) ;
132
+
133
+ context. schema . objects . insert (
134
+ "Organization" . to_string ( ) , GqlObject {
135
+ name : "Organization" . to_string ( ) ,
136
+ fields : vec ! [
137
+ GqlObjectField {
138
+ name: "title" . to_string( ) ,
139
+ type_: FieldType :: Named ( Ident :: new( "String" , Span :: call_site( ) ) ) ,
140
+ } ,
141
+ GqlObjectField {
142
+ name: "created_at" . to_string( ) ,
143
+ type_: FieldType :: Named ( Ident :: new( "Date" , Span :: call_site( ) ) ) ,
144
+ }
145
+ ] ,
146
+ }
147
+ ) ;
148
+
149
+ let result = union. response_for_selection (
150
+ & context,
151
+ & selection,
152
+ & prefix,
153
+ ) ;
154
+
155
+ assert ! ( result. is_ok( ) ) ;
156
+
157
+ assert_eq ! (
158
+ result. unwrap( ) . to_string( ) ,
159
+ vec![
160
+ "# [ derive ( Debug , Serialize , Deserialize ) ] " ,
161
+ "pub struct MeowOnUser { first_name : String , } " ,
162
+ "# [ derive ( Debug , Serialize , Deserialize ) ] " ,
163
+ "pub struct MeowOnOrganization { title : String , } " ,
164
+ "# [ derive ( Deserialize ) ] pub struct Meow { on_user : MeowOnUser , on_organization : MeowOnOrganization }" ,
165
+ ] . into_iter( ) . collect:: <String >( ) ,
166
+ ) ;
167
+ }
72
168
}
0 commit comments