rails-graphql 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/gql_parser.c +4 -4
- data/ext/shared.c +6 -8
- data/ext/shared.h +5 -1
- data/lib/gql_parser.so +0 -0
- data/lib/rails/graphql/alternative/field_set.rb +3 -3
- data/lib/rails/graphql/alternative/query.rb +1 -1
- data/lib/rails/graphql/alternative.rb +1 -0
- data/lib/rails/graphql/helpers/with_fields.rb +4 -4
- data/lib/rails/graphql/version.rb +1 -1
- data/test/assets/alternative.gql +323 -0
- data/test/integration/alternative_test.rb +145 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3e7d0465d49d0e8eef8d0672cc60cbf8f15e5ee8cb11bf765a2a944b4d5aab33
|
4
|
+
data.tar.gz: 6ada22cc356373aa92a4986029092fb63b16532e8a5df16798b15f17c4d8221a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a62b2abf73592f82b4b5b2b290dde535b32054903d6a330808c03137369df0d1962576eaf4658ef42e08803ba82fed36963d75dd72101d0ec1e3362ae2d9ceb1
|
7
|
+
data.tar.gz: d5f8e3b75c6458623e9af9a493113ac230855fadd7bdb93b4bc2f3165a3bf0ed6a7cd6697a05199749a69c3b55412cd849fbc92cd25edbbc331493f5c5989df5
|
data/ext/gql_parser.c
CHANGED
@@ -83,7 +83,7 @@ VALUE gql_parse_execution(VALUE self, VALUE document)
|
|
83
83
|
{
|
84
84
|
// Try to upgrade if the token is a name
|
85
85
|
if (scanner.lexeme == gql_i_name)
|
86
|
-
scanner.lexeme =
|
86
|
+
scanner.lexeme = GQL_SAFE_NAME_TO_KEYWORD(&scanner, GQL_EXECUTION_KEYWORDS);
|
87
87
|
|
88
88
|
// It can contain either operations or fragments, anything else is unknown and an error
|
89
89
|
if (QGL_I_OPERATION(scanner.lexeme) || scanner.lexeme == gql_is_op_curly)
|
@@ -157,14 +157,14 @@ VALUE gql_parse_fragment(struct gql_scanner *scanner)
|
|
157
157
|
gql_next_lexeme_no_comments(scanner);
|
158
158
|
if (scanner->lexeme != gql_i_name)
|
159
159
|
return gql_nil_and_unknown(scanner);
|
160
|
-
else if (
|
160
|
+
else if (GQL_SAFE_NAME_TO_KEYWORD(scanner, GQL_EXECUTION_KEYWORDS) == gql_ie_on)
|
161
161
|
return gql_nil_and_unknown(scanner);
|
162
162
|
|
163
163
|
// Save the name of the fragment
|
164
164
|
GQL_ASSIGN_TOKEN_AND_NEXT(pieces[0], scanner);
|
165
165
|
|
166
166
|
// If we don't have an "on" next, we have a problem
|
167
|
-
if (
|
167
|
+
if (GQL_SAFE_NAME_TO_KEYWORD(scanner, GQL_EXECUTION_KEYWORDS) != gql_ie_on)
|
168
168
|
return gql_nil_and_unknown(scanner);
|
169
169
|
|
170
170
|
// Skip the on and ensure that next is a name
|
@@ -481,7 +481,7 @@ VALUE gql_parse_spread(struct gql_scanner *scanner)
|
|
481
481
|
if (scanner->lexeme == gql_i_name)
|
482
482
|
{
|
483
483
|
// Upgrade the name because it will decide if it is an inline spread or not
|
484
|
-
scanner->lexeme =
|
484
|
+
scanner->lexeme = GQL_SAFE_NAME_TO_KEYWORD(scanner, GQL_EXECUTION_KEYWORDS);
|
485
485
|
|
486
486
|
// If we are at "on" then we have an inline spread, otherwise a fragment referenced by name
|
487
487
|
if (scanner->lexeme == gql_ie_on)
|
data/ext/shared.c
CHANGED
@@ -65,16 +65,17 @@ enum gql_lexeme gql_upgrade_basis(const char *upgrade_from[])
|
|
65
65
|
}
|
66
66
|
|
67
67
|
// This checks if the identifier in the scanner should be upgraded to a keyword
|
68
|
-
enum gql_lexeme gql_name_to_keyword(struct gql_scanner *scanner, const char *
|
68
|
+
enum gql_lexeme gql_name_to_keyword(struct gql_scanner *scanner, const char *keywords[], unsigned int size)
|
69
69
|
{
|
70
70
|
unsigned long pos, len = GQL_SCAN_SIZE(scanner);
|
71
|
-
unsigned int valid = 0
|
71
|
+
unsigned int valid = 0;
|
72
72
|
const char *keyword;
|
73
73
|
|
74
74
|
// Check until it finds the end of the array
|
75
|
-
|
75
|
+
for (size_t i = 0; i < size; ++i)
|
76
76
|
{
|
77
77
|
// Move ot the next item and check the current for different size
|
78
|
+
keyword = keywords[i];
|
78
79
|
if(strlen(keyword) == len)
|
79
80
|
{
|
80
81
|
// We cannot use the normal strcomp because we are comparing a mid part of the string
|
@@ -85,11 +86,8 @@ enum gql_lexeme gql_name_to_keyword(struct gql_scanner *scanner, const char *upg
|
|
85
86
|
}
|
86
87
|
|
87
88
|
// Only return if valid was kept as true
|
88
|
-
if (valid == 1) return gql_upgrade_basis(
|
89
|
+
if (valid == 1) return gql_upgrade_basis(keywords) + i;
|
89
90
|
}
|
90
|
-
|
91
|
-
// Move to the next index
|
92
|
-
i++;
|
93
91
|
}
|
94
92
|
|
95
93
|
// Return name if was not able to upgrade to a keyword
|
@@ -438,7 +436,7 @@ VALUE gql_value_to_rb(struct gql_scanner *scanner, int accept_var)
|
|
438
436
|
// If it's a name, then it can be a keyword or a enum value
|
439
437
|
if (scanner->lexeme == gql_i_name)
|
440
438
|
{
|
441
|
-
scanner->lexeme =
|
439
|
+
scanner->lexeme = GQL_SAFE_NAME_TO_KEYWORD(scanner, GQL_VALUE_KEYWORDS);
|
442
440
|
if (scanner->lexeme == gql_iv_true)
|
443
441
|
return Qtrue;
|
444
442
|
else if (scanner->lexeme == gql_iv_false)
|
data/ext/shared.h
CHANGED
@@ -70,6 +70,10 @@
|
|
70
70
|
rb_ary_push(source, value); \
|
71
71
|
})
|
72
72
|
|
73
|
+
#define GQL_SAFE_NAME_TO_KEYWORD(scanner, source) ({ \
|
74
|
+
gql_name_to_keyword(scanner, source, (sizeof(source) / sizeof(char *))); \
|
75
|
+
})
|
76
|
+
|
73
77
|
enum gql_lexeme
|
74
78
|
{
|
75
79
|
// Basic identifiers
|
@@ -153,7 +157,7 @@ void gql_debug_print(const char *message);
|
|
153
157
|
struct gql_scanner gql_new_scanner(VALUE source);
|
154
158
|
|
155
159
|
enum gql_lexeme gql_upgrade_basis(const char *upgrade_from[]);
|
156
|
-
enum gql_lexeme gql_name_to_keyword(struct gql_scanner *scanner, const char *
|
160
|
+
enum gql_lexeme gql_name_to_keyword(struct gql_scanner *scanner, const char *keywords[], unsigned int size);
|
157
161
|
|
158
162
|
enum gql_lexeme gql_read_name(struct gql_scanner *scanner);
|
159
163
|
enum gql_lexeme gql_read_comment(struct gql_scanner *scanner);
|
data/lib/gql_parser.so
CHANGED
Binary file
|
@@ -12,7 +12,7 @@ module Rails
|
|
12
12
|
|
13
13
|
include Helpers::Instantiable
|
14
14
|
|
15
|
-
self.field_type = Field::OutputField
|
15
|
+
self.field_type = GraphQL::Field::OutputField
|
16
16
|
self.valid_field_types = Type::Object.valid_field_types
|
17
17
|
|
18
18
|
def self.i18n_scope
|
@@ -33,7 +33,7 @@ module Rails
|
|
33
33
|
#
|
34
34
|
# Same as a +FieldSet+ but for mutation fields
|
35
35
|
MutationSet = Class.new(FieldSet)
|
36
|
-
MutationSet.field_type = Field::MutationField
|
36
|
+
MutationSet.field_type = GraphQL::Field::MutationField
|
37
37
|
MutationSet.redefine_singleton_method(:i18n_scope) { :mutation }
|
38
38
|
|
39
39
|
|
@@ -41,7 +41,7 @@ module Rails
|
|
41
41
|
#
|
42
42
|
# Same as a +FieldSet+ but for subscription fields
|
43
43
|
SubscriptionSet = Class.new(FieldSet)
|
44
|
-
SubscriptionSet.field_type = Field::SubscriptionField
|
44
|
+
SubscriptionSet.field_type = GraphQL::Field::SubscriptionField
|
45
45
|
SubscriptionSet.redefine_singleton_method(:i18n_scope) { :subscription }
|
46
46
|
end
|
47
47
|
end
|
@@ -52,7 +52,7 @@ module Rails
|
|
52
52
|
def define_field(field_name = nil, type = :any, **xargs, &block)
|
53
53
|
field_name ||= anonymous? ? '_anonymous' : begin
|
54
54
|
type_module = type_field_class.to_s.classify.pluralize
|
55
|
-
user_name = name.split(+"#{type_module}::")
|
55
|
+
user_name = name.split(+"#{type_module}::")&.at(1)
|
56
56
|
user_name ||= name.delete_prefix('GraphQL::')
|
57
57
|
user_name.tr(':', '')
|
58
58
|
end
|
@@ -137,19 +137,19 @@ module Rails
|
|
137
137
|
def import(source)
|
138
138
|
# Import an alternative declaration of a field
|
139
139
|
if source.is_a?(Module) && source <= Alternative::Query
|
140
|
-
return proxy_field(
|
140
|
+
return proxy_field(source.field)
|
141
141
|
end
|
142
142
|
|
143
143
|
case source
|
144
144
|
when Array
|
145
145
|
# Import a list of fields
|
146
|
-
source.each { |field| proxy_field(
|
146
|
+
source.each { |field| proxy_field(field) }
|
147
147
|
when Hash, Concurrent::Map
|
148
148
|
# Import a keyed list of fields
|
149
|
-
source.each_value { |field| proxy_field(
|
149
|
+
source.each_value { |field| proxy_field(field) }
|
150
150
|
when Helpers::WithFields
|
151
151
|
# Import a set of fields
|
152
|
-
source.fields.each_value { |field| proxy_field(
|
152
|
+
source.fields.each_value { |field| proxy_field(field) }
|
153
153
|
else
|
154
154
|
return if GraphQL.config.silence_import_warnings
|
155
155
|
GraphQL.logger.warn(+"Unable to import #{source.inspect} into #{self.name}.")
|
@@ -0,0 +1,323 @@
|
|
1
|
+
schema {
|
2
|
+
query: _Query
|
3
|
+
mutation: _Mutation
|
4
|
+
}
|
5
|
+
|
6
|
+
"The Boolean scalar type represents true or false."
|
7
|
+
scalar Boolean
|
8
|
+
|
9
|
+
"The Float scalar type represents signed double-precision fractional values."
|
10
|
+
scalar Float
|
11
|
+
|
12
|
+
"""
|
13
|
+
The ID scalar type represents a unique identifier and it is serialized in the same
|
14
|
+
way as a String but it accepts both numeric and string based values as input.
|
15
|
+
"""
|
16
|
+
scalar ID
|
17
|
+
|
18
|
+
"The Int scalar type represents a signed 32-bit numeric non-fractional value."
|
19
|
+
scalar Int
|
20
|
+
|
21
|
+
"""
|
22
|
+
The String scalar type represents textual data, represented as UTF-8 character
|
23
|
+
sequences.
|
24
|
+
"""
|
25
|
+
scalar String
|
26
|
+
|
27
|
+
"The valid locations that a directive may be placed."
|
28
|
+
enum __DirectiveLocation {
|
29
|
+
"Mark as a executable directive usable on query objects."
|
30
|
+
QUERY
|
31
|
+
|
32
|
+
"Mark as a executable directive usable on mutation objects."
|
33
|
+
MUTATION
|
34
|
+
|
35
|
+
"Mark as a executable directive usable on subscription objects."
|
36
|
+
SUBSCRIPTION
|
37
|
+
|
38
|
+
"Mark as a executable directive usable on field objects."
|
39
|
+
FIELD
|
40
|
+
|
41
|
+
"Mark as a executable directive usable on fragment definition objects."
|
42
|
+
FRAGMENT_DEFINITION
|
43
|
+
|
44
|
+
"Mark as a executable directive usable on fragment spread objects."
|
45
|
+
FRAGMENT_SPREAD
|
46
|
+
|
47
|
+
"Mark as a executable directive usable on inline fragment objects."
|
48
|
+
INLINE_FRAGMENT
|
49
|
+
|
50
|
+
"Mark as a type system directive usable on schema definitions."
|
51
|
+
SCHEMA
|
52
|
+
|
53
|
+
"Mark as a type system directive usable on scalar definitions."
|
54
|
+
SCALAR
|
55
|
+
|
56
|
+
"Mark as a type system directive usable on object definitions."
|
57
|
+
OBJECT
|
58
|
+
|
59
|
+
"Mark as a type system directive usable on field definitions."
|
60
|
+
FIELD_DEFINITION
|
61
|
+
|
62
|
+
"Mark as a type system directive usable on argument definitions."
|
63
|
+
ARGUMENT_DEFINITION
|
64
|
+
|
65
|
+
"Mark as a type system directive usable on interface definitions."
|
66
|
+
INTERFACE
|
67
|
+
|
68
|
+
"Mark as a type system directive usable on union definitions."
|
69
|
+
UNION
|
70
|
+
|
71
|
+
"Mark as a type system directive usable on enum definitions."
|
72
|
+
ENUM
|
73
|
+
|
74
|
+
"Mark as a type system directive usable on enum value definitions."
|
75
|
+
ENUM_VALUE
|
76
|
+
|
77
|
+
"Mark as a type system directive usable on input object definitions."
|
78
|
+
INPUT_OBJECT
|
79
|
+
|
80
|
+
"Mark as a type system directive usable on input field definitions."
|
81
|
+
INPUT_FIELD_DEFINITION
|
82
|
+
}
|
83
|
+
|
84
|
+
"""
|
85
|
+
The fundamental unit of any GraphQL Schema is the type.
|
86
|
+
This enum enlist all the valid base types.
|
87
|
+
"""
|
88
|
+
enum __TypeKind {
|
89
|
+
"Scalar types represent primitive leaf values in a GraphQL type system.\n"
|
90
|
+
SCALAR
|
91
|
+
|
92
|
+
"Objects represent a list of named fields, each of which yield a value of a\nspecific type.\n"
|
93
|
+
OBJECT
|
94
|
+
|
95
|
+
"Interfaces represent a list of named fields and their types.\n"
|
96
|
+
INTERFACE
|
97
|
+
|
98
|
+
"Unions represent an object that could be one of a list of GraphQL Object types.\n"
|
99
|
+
UNION
|
100
|
+
|
101
|
+
"Enum types, like scalar types, also represent leaf values in a GraphQL\ntype system. However Enum types describe the set of possible values.\n"
|
102
|
+
ENUM
|
103
|
+
|
104
|
+
"Objects represent a list of named fields, each of which yield a value of\na specific type.\n"
|
105
|
+
INPUT_OBJECT
|
106
|
+
|
107
|
+
"A GraphQL list is a special collection type which declares the type of\neach item in the List (referred to as the item type of the list).\n"
|
108
|
+
LIST
|
109
|
+
|
110
|
+
"This type wraps an underlying type, and this type acts identically to that wrapped\ntype, with the exception that null is not a valid response for the wrapping type.\n"
|
111
|
+
NON_NULL
|
112
|
+
}
|
113
|
+
|
114
|
+
type Sample {
|
115
|
+
sample: String
|
116
|
+
}
|
117
|
+
|
118
|
+
type _Mutation {
|
119
|
+
sampleMutation: String
|
120
|
+
|
121
|
+
sampleMutationA: String
|
122
|
+
|
123
|
+
sampleMutationB: String
|
124
|
+
}
|
125
|
+
|
126
|
+
type _Query {
|
127
|
+
__schema: __Schema!
|
128
|
+
|
129
|
+
__type(name: String!): __Type
|
130
|
+
|
131
|
+
sampleObject: Sample
|
132
|
+
|
133
|
+
sampleQuery: String
|
134
|
+
|
135
|
+
sampleQueryA: String
|
136
|
+
|
137
|
+
sampleQueryB: String
|
138
|
+
}
|
139
|
+
|
140
|
+
"""
|
141
|
+
Directives provide a way to describe alternate runtime execution
|
142
|
+
and type validation behavior in a GraphQL document.
|
143
|
+
|
144
|
+
In some cases, you need to provide options to alter GraphQL's execution
|
145
|
+
behavior in ways field arguments will not suffice, such as conditionally
|
146
|
+
including or skipping a field. Directives provide this by describing
|
147
|
+
additional information to the executor.
|
148
|
+
"""
|
149
|
+
# Assigned to Rails::GraphQL::Directive class
|
150
|
+
type __Directive {
|
151
|
+
args: [__InputValue!]!
|
152
|
+
|
153
|
+
description: String
|
154
|
+
|
155
|
+
isRepeatable: Boolean!
|
156
|
+
|
157
|
+
locations: [__DirectiveLocation!]!
|
158
|
+
|
159
|
+
name: String!
|
160
|
+
}
|
161
|
+
|
162
|
+
"""
|
163
|
+
One of the values of an Enum object. It is unique within the Enum set
|
164
|
+
of values. It's a string representation, not a numeric representation,
|
165
|
+
of a value kept as all caps (ie. ONE_VALUE).
|
166
|
+
"""
|
167
|
+
type __EnumValue {
|
168
|
+
deprecationReason: String
|
169
|
+
|
170
|
+
description: String
|
171
|
+
|
172
|
+
isDeprecated: Boolean!
|
173
|
+
|
174
|
+
name: String!
|
175
|
+
}
|
176
|
+
|
177
|
+
"""
|
178
|
+
Fields are the elements that compose both Objects and Interfaces. Each
|
179
|
+
field in these other objects may contain arguments and always yields
|
180
|
+
a value of a specific type.
|
181
|
+
"""
|
182
|
+
# Assigned to Rails::GraphQL::Field class
|
183
|
+
type __Field {
|
184
|
+
args: [__InputValue!]!
|
185
|
+
|
186
|
+
deprecationReason: String
|
187
|
+
|
188
|
+
description: String
|
189
|
+
|
190
|
+
isDeprecated: Boolean!
|
191
|
+
|
192
|
+
name: String!
|
193
|
+
|
194
|
+
type: __Type!
|
195
|
+
}
|
196
|
+
|
197
|
+
"""
|
198
|
+
Arguments provided to Fields or Directives and the input fields of an
|
199
|
+
InputObject are represented as Input Values which describe their type
|
200
|
+
and optionally a default value.
|
201
|
+
"""
|
202
|
+
# Assigned to Rails::GraphQL::Field::InputField class
|
203
|
+
type __InputValue {
|
204
|
+
defaultValue: String
|
205
|
+
|
206
|
+
description: String
|
207
|
+
|
208
|
+
name: String!
|
209
|
+
|
210
|
+
type: __Type!
|
211
|
+
}
|
212
|
+
|
213
|
+
"""
|
214
|
+
A GraphQL service's collective type system capabilities are referred
|
215
|
+
to as that service's "schema". A schema is defined in terms of the
|
216
|
+
types and directives it supports as well as the root operation types
|
217
|
+
for each kind of operation: query, mutation, and subscription; this
|
218
|
+
determines the place in the type system where those operations begin.
|
219
|
+
"""
|
220
|
+
# Assigned to Rails::GraphQL::Schema class
|
221
|
+
type __Schema {
|
222
|
+
directives: [__Directive!]!
|
223
|
+
|
224
|
+
mutationType: __Type
|
225
|
+
|
226
|
+
queryType: __Type!
|
227
|
+
|
228
|
+
subscriptionType: __Type
|
229
|
+
|
230
|
+
types: [__Type!]!
|
231
|
+
}
|
232
|
+
|
233
|
+
"""
|
234
|
+
The fundamental unit of any GraphQL Schema is the type. There are six
|
235
|
+
kinds of named type definitions in GraphQL, and two wrapping types.
|
236
|
+
|
237
|
+
The most basic type is a +Scalar+. A scalar represents a primitive value,
|
238
|
+
like a string or an integer.
|
239
|
+
|
240
|
+
+Scalars+ and +Enums+ form the leaves in response trees; the intermediate
|
241
|
+
levels are +Object+ types, which define a set of fields.
|
242
|
+
|
243
|
+
An +Interface+ defines a list of fields; +Object+ types that implement
|
244
|
+
that interface are guaranteed to implement those fields.
|
245
|
+
|
246
|
+
A +Union+ defines a list of possible types; similar to interfaces,
|
247
|
+
whenever the type system claims a union will be returned, one of the
|
248
|
+
possible types will be returned.
|
249
|
+
|
250
|
+
Finally, oftentimes it is useful to provide complex structs as inputs
|
251
|
+
to GraphQL field arguments or variables; the +Input Object+ type allows
|
252
|
+
the schema to define exactly what data is expected.
|
253
|
+
"""
|
254
|
+
# Assigned to Rails::GraphQL::Type class
|
255
|
+
type __Type {
|
256
|
+
description: String
|
257
|
+
|
258
|
+
"ENUM only"
|
259
|
+
enumValues(includeDeprecated: Boolean = false): [__EnumValue!]
|
260
|
+
|
261
|
+
"OBJECT and INTERFACE only"
|
262
|
+
fields(includeDeprecated: Boolean = false): [__Field!]
|
263
|
+
|
264
|
+
"INPUT_OBJECT only"
|
265
|
+
inputFields: [__InputValue!]
|
266
|
+
|
267
|
+
"OBJECT only"
|
268
|
+
interfaces: [__Type!]
|
269
|
+
|
270
|
+
kind: __TypeKind!
|
271
|
+
|
272
|
+
name: String
|
273
|
+
|
274
|
+
"NON_NULL and LIST only"
|
275
|
+
ofType: __Type
|
276
|
+
|
277
|
+
"INTERFACE and UNION only"
|
278
|
+
possibleTypes: [__Type!]
|
279
|
+
|
280
|
+
specifiedByURL: String
|
281
|
+
}
|
282
|
+
|
283
|
+
"""
|
284
|
+
Indicate deprecated portions of a GraphQL service's schema, such as deprecated
|
285
|
+
fields on a type or deprecated enum values.
|
286
|
+
"""
|
287
|
+
directive @deprecated(
|
288
|
+
|
289
|
+
"""
|
290
|
+
Explain why the underlying element was marked as deprecated. If possible,
|
291
|
+
indicate what element should be used instead. This description is formatted
|
292
|
+
using Markdown syntax (as specified by [CommonMark](http://commonmark.org/)).
|
293
|
+
"""
|
294
|
+
reason: String
|
295
|
+
|
296
|
+
) on FIELD_DEFINITION | ENUM_VALUE
|
297
|
+
|
298
|
+
"Allows for conditional inclusion during execution as described by the if argument."
|
299
|
+
directive @include(
|
300
|
+
|
301
|
+
"When false, the underlying element will be automatically marked as null."
|
302
|
+
if: Boolean!
|
303
|
+
|
304
|
+
) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
|
305
|
+
|
306
|
+
"Allows for conditional exclusion during execution as described by the if argument."
|
307
|
+
directive @skip(
|
308
|
+
|
309
|
+
"When true, the underlying element will be automatically marked as null."
|
310
|
+
if: Boolean!
|
311
|
+
|
312
|
+
) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
|
313
|
+
|
314
|
+
"""
|
315
|
+
A built-in directive used within the type system definition language to provide
|
316
|
+
a scalar specification URL for specifying the behavior of custom scalar types.
|
317
|
+
"""
|
318
|
+
directive @specifiedBy(
|
319
|
+
|
320
|
+
"Point to a human-readable specification of the data format."
|
321
|
+
url: String!
|
322
|
+
|
323
|
+
) on SCALAR
|
@@ -0,0 +1,145 @@
|
|
1
|
+
require 'integration/config'
|
2
|
+
|
3
|
+
class Integration_AlternativeTest < GraphQL::IntegrationTestCase
|
4
|
+
module Alternatives
|
5
|
+
# A regular field that is imported into an object
|
6
|
+
class SampleField < GraphQL::Field
|
7
|
+
define_field :sample, :string
|
8
|
+
|
9
|
+
def resolve
|
10
|
+
"#{current[:sample]} Resolved"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# A simple query field that can called directly
|
15
|
+
class SampleQuery < GraphQL::Query
|
16
|
+
define_field :sample_query, :string
|
17
|
+
|
18
|
+
def resolve
|
19
|
+
'Sample Query'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# A simple mutation field that can called directly
|
24
|
+
class SampleMutation < GraphQL::Mutation
|
25
|
+
define_field :sample_mutation, :string
|
26
|
+
|
27
|
+
def perform
|
28
|
+
request.extensions['mutation'] = 'Ok!'
|
29
|
+
end
|
30
|
+
|
31
|
+
def resolve
|
32
|
+
'Sample Mutation'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# A set of query fields
|
37
|
+
class SampleQuerySet < GraphQL::QuerySet
|
38
|
+
field :sample_query_a, :string
|
39
|
+
field :sample_query_b, :string
|
40
|
+
|
41
|
+
def sample_query_a
|
42
|
+
'Sample Query A'
|
43
|
+
end
|
44
|
+
|
45
|
+
def sample_query_b
|
46
|
+
'Sample Query B'
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# A set of mutation fields
|
51
|
+
class SampleMutationSet < GraphQL::MutationSet
|
52
|
+
field :sample_mutation_a, :string
|
53
|
+
field :sample_mutation_b, :string
|
54
|
+
|
55
|
+
def sample_mutation_a!
|
56
|
+
request.extensions['mutationA'] = 'Ok!'
|
57
|
+
end
|
58
|
+
|
59
|
+
def sample_mutation_a
|
60
|
+
'Sample Mutation A'
|
61
|
+
end
|
62
|
+
|
63
|
+
def sample_mutation_b!
|
64
|
+
request.extensions['mutationB'] = 'Ok!'
|
65
|
+
end
|
66
|
+
|
67
|
+
def sample_mutation_b
|
68
|
+
'Sample Mutation B'
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class SCHEMA < GraphQL::Schema
|
74
|
+
namespace :authorization
|
75
|
+
|
76
|
+
configure do |config|
|
77
|
+
config.enable_string_collector = false
|
78
|
+
config.default_response_format = :json
|
79
|
+
end
|
80
|
+
|
81
|
+
object 'Sample' do
|
82
|
+
import Alternatives::SampleField
|
83
|
+
end
|
84
|
+
|
85
|
+
query_fields do
|
86
|
+
import Alternatives::SampleQuery
|
87
|
+
import Alternatives::SampleQuerySet
|
88
|
+
field :sample_object, 'Sample'
|
89
|
+
end
|
90
|
+
|
91
|
+
mutation_fields do
|
92
|
+
import Alternatives::SampleMutation
|
93
|
+
import Alternatives::SampleMutationSet
|
94
|
+
end
|
95
|
+
|
96
|
+
def sample_object
|
97
|
+
{ sample: 'Sample Field' }
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_query_object
|
102
|
+
result = { data: { sampleObject: { sample: 'Sample Field Resolved' } } }
|
103
|
+
assert_result(result, '{ sampleObject { sample } }')
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_query_field
|
107
|
+
assert_result({ data: { sampleQuery: 'Sample Query' } }, '{ sampleQuery }')
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_query_field_set
|
111
|
+
assert_result({ data: { sampleQueryA: 'Sample Query A' } }, '{ sampleQueryA }')
|
112
|
+
assert_result({ data: { sampleQueryB: 'Sample Query B' } }, '{ sampleQueryB }')
|
113
|
+
|
114
|
+
result = { data: { sampleQueryA: 'Sample Query A', sampleQueryB: 'Sample Query B' } }
|
115
|
+
assert_result(result, '{ sampleQueryA sampleQueryB }')
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_mutation_field
|
119
|
+
result = { data: { sampleMutation: 'Sample Mutation' }, extensions: { mutation: 'Ok!' } }
|
120
|
+
assert_result(result, 'mutation { sampleMutation }')
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_mutation_field_set
|
124
|
+
result = { data: { sampleMutationA: 'Sample Mutation A' }, extensions: { mutationA: 'Ok!' } }
|
125
|
+
assert_result(result, 'mutation { sampleMutationA }')
|
126
|
+
|
127
|
+
result = { data: { sampleMutationB: 'Sample Mutation B' }, extensions: { mutationB: 'Ok!' } }
|
128
|
+
assert_result(result, 'mutation { sampleMutationB }')
|
129
|
+
|
130
|
+
result = {
|
131
|
+
data: { sampleMutationA: 'Sample Mutation A', sampleMutationB: 'Sample Mutation B' },
|
132
|
+
extensions: { mutationA: 'Ok!', mutationB: 'Ok!' },
|
133
|
+
}
|
134
|
+
|
135
|
+
assert_result(result, 'mutation { sampleMutationA sampleMutationB }')
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_gql_introspection
|
139
|
+
result = SCHEMA.to_gql
|
140
|
+
expected = gql_file('alternative').split('').sort.join.squish
|
141
|
+
|
142
|
+
# File.write('test/assets/alternative.gql', result)
|
143
|
+
assert_equal(expected, result.split('').sort.join.squish)
|
144
|
+
end
|
145
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails-graphql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Carlos Silva
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-02-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -339,6 +339,7 @@ files:
|
|
339
339
|
- lib/rails/graphql/type_map.rb
|
340
340
|
- lib/rails/graphql/uri.rb
|
341
341
|
- lib/rails/graphql/version.rb
|
342
|
+
- test/assets/alternative.gql
|
342
343
|
- test/assets/en.yml
|
343
344
|
- test/assets/introspection-db.json
|
344
345
|
- test/assets/introspection-mem.txt
|
@@ -375,6 +376,7 @@ files:
|
|
375
376
|
- test/graphql/type_map_test.rb
|
376
377
|
- test/graphql/type_test.rb
|
377
378
|
- test/graphql_test.rb
|
379
|
+
- test/integration/alternative_test.rb
|
378
380
|
- test/integration/authorization_test.rb
|
379
381
|
- test/integration/config.rb
|
380
382
|
- test/integration/customization_test.rb
|
@@ -424,6 +426,7 @@ signing_key:
|
|
424
426
|
specification_version: 4
|
425
427
|
summary: GraphQL meets RoR with the most Ruby-like DSL
|
426
428
|
test_files:
|
429
|
+
- test/assets/alternative.gql
|
427
430
|
- test/assets/en.yml
|
428
431
|
- test/assets/introspection-db.json
|
429
432
|
- test/assets/introspection-mem.txt
|
@@ -460,6 +463,7 @@ test_files:
|
|
460
463
|
- test/graphql/type_map_test.rb
|
461
464
|
- test/graphql/type_test.rb
|
462
465
|
- test/graphql_test.rb
|
466
|
+
- test/integration/alternative_test.rb
|
463
467
|
- test/integration/authorization_test.rb
|
464
468
|
- test/integration/config.rb
|
465
469
|
- test/integration/customization_test.rb
|