rails-graphql 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 38fafc81ae4e9f8c11c4d1495b8290656dcf388ac0b6d5536829e0f77ee09bb2
4
- data.tar.gz: 8a8298e375df5ac6905b24deeacf29ca2fd7b4dc39dfb43601ba2331828ac939
3
+ metadata.gz: 3e7d0465d49d0e8eef8d0672cc60cbf8f15e5ee8cb11bf765a2a944b4d5aab33
4
+ data.tar.gz: 6ada22cc356373aa92a4986029092fb63b16532e8a5df16798b15f17c4d8221a
5
5
  SHA512:
6
- metadata.gz: fa92f53a2111c001863967bca893a25bab09f9a9c163af945631a15054c865db2e9102467e8c85ac1c3cbc0591c377a97f98c2439bdc94c72694d72cbef99e05
7
- data.tar.gz: d994c9ff91179fbd72ecb3afde6f3bb005805697ebe994cfcc88b2bc9720e30f16ac76f6dab81b65760ad3e61af5db427d9a5e9118f6222b756df00c35b499d7
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 = gql_name_to_keyword(&scanner, GQL_EXECUTION_KEYWORDS);
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 (gql_name_to_keyword(scanner, GQL_EXECUTION_KEYWORDS) == gql_ie_on)
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 (gql_name_to_keyword(scanner, GQL_EXECUTION_KEYWORDS) != gql_ie_on)
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 = gql_name_to_keyword(scanner, GQL_EXECUTION_KEYWORDS);
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 *upgrade_from[])
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, i = 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
- while ((keyword = upgrade_from[i]) != 0)
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(upgrade_from) + i;
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 = gql_name_to_keyword(scanner, GQL_VALUE_KEYWORDS);
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 *upgrade_from[]);
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);
@@ -37,6 +37,11 @@ Rails::GraphQL.configure do |config|
37
37
  # different suffix, change this value to it.
38
38
  # config.auto_suffix_input_objects = 'Input'
39
39
 
40
+ # Set if the server should allow strings be used as input for ENUM inputs.
41
+ # It means that operations will support quotes for ENUM values embedded in
42
+ # the documents (heredoc won't be accepted).
43
+ # config.allow_string_as_enum_input = false
44
+
40
45
  # Introspection is enabled by default. It is recommended to only use
41
46
  # introspection during development and tests, never in production.
42
47
  # This can also be set per schema level.
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}::")[1]
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
@@ -16,6 +16,7 @@ module Rails
16
16
 
17
17
  autoload_at "#{__dir__}/alternative/field_set" do
18
18
  autoload :FieldSet
19
+ autoload :QuerySet
19
20
  autoload :MutationSet
20
21
  autoload :SubscriptionSet
21
22
  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(type, source.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(type, 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(type, 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(type, 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}.")
@@ -19,6 +19,8 @@ module Rails
19
19
  # Helper method to initialize an operation given the node
20
20
  def build(request, node)
21
21
  request.build(const_get(node.type.to_s.classify, false), request, node)
22
+ rescue ::NameError
23
+ raise NameError, +%[Unable to initialize "#{node.type}" operation.]
22
24
  end
23
25
 
24
26
  # Rewrite the kind to always return +:operation+
@@ -14,7 +14,7 @@ module Rails
14
14
  module VERSION
15
15
  MAJOR = 1
16
16
  MINOR = 0
17
- TINY = 0
17
+ TINY = 2
18
18
  PRE = nil
19
19
 
20
20
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
@@ -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,21 @@
1
+ require 'config'
2
+
3
+ class GraphQL_Request_Component_OperationTest < GraphQL::TestCase
4
+ def test_build
5
+ request = Object.new
6
+ request.define_singleton_method(:build) { |klass, *| klass }
7
+
8
+ assert_equal(klass::Query, klass.build(request, new_token('', :query)))
9
+ assert_equal(klass::Mutation, klass.build(request, new_token('', :mutation)))
10
+ assert_equal(klass::Subscription, klass.build(request, new_token('', :subscription)))
11
+
12
+ assert_raises(Rails::GraphQL::NameError) { klass.build(request, new_token('', '')) }
13
+ assert_raises(Rails::GraphQL::NameError) { klass.build(request, new_token('', :field)) }
14
+ end
15
+
16
+ private
17
+
18
+ def klass
19
+ Rails::GraphQL::Request::Component::Operation
20
+ end
21
+ end
@@ -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.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: 2023-08-30 00:00:00.000000000 Z
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
@@ -349,6 +350,7 @@ files:
349
350
  - test/assets/sqlite.gql
350
351
  - test/assets/translate.gql
351
352
  - test/config.rb
353
+ - test/graphql/request/component/operation_test.rb
352
354
  - test/graphql/request/context_test.rb
353
355
  - test/graphql/schema_test.rb
354
356
  - test/graphql/source_test.rb
@@ -374,6 +376,7 @@ files:
374
376
  - test/graphql/type_map_test.rb
375
377
  - test/graphql/type_test.rb
376
378
  - test/graphql_test.rb
379
+ - test/integration/alternative_test.rb
377
380
  - test/integration/authorization_test.rb
378
381
  - test/integration/config.rb
379
382
  - test/integration/customization_test.rb
@@ -423,6 +426,7 @@ signing_key:
423
426
  specification_version: 4
424
427
  summary: GraphQL meets RoR with the most Ruby-like DSL
425
428
  test_files:
429
+ - test/assets/alternative.gql
426
430
  - test/assets/en.yml
427
431
  - test/assets/introspection-db.json
428
432
  - test/assets/introspection-mem.txt
@@ -433,6 +437,7 @@ test_files:
433
437
  - test/assets/sqlite.gql
434
438
  - test/assets/translate.gql
435
439
  - test/config.rb
440
+ - test/graphql/request/component/operation_test.rb
436
441
  - test/graphql/request/context_test.rb
437
442
  - test/graphql/schema_test.rb
438
443
  - test/graphql/source_test.rb
@@ -458,6 +463,7 @@ test_files:
458
463
  - test/graphql/type_map_test.rb
459
464
  - test/graphql/type_test.rb
460
465
  - test/graphql_test.rb
466
+ - test/integration/alternative_test.rb
461
467
  - test/integration/authorization_test.rb
462
468
  - test/integration/config.rb
463
469
  - test/integration/customization_test.rb