graphql 1.8.7 → 1.8.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/graphql/enum_type.rb +4 -0
- data/lib/graphql/execution/multiplex.rb +1 -1
- data/lib/graphql/schema/argument.rb +1 -0
- data/lib/graphql/schema/enum_value.rb +1 -0
- data/lib/graphql/schema/field.rb +1 -0
- data/lib/graphql/schema/interface.rb +1 -0
- data/lib/graphql/schema/member.rb +2 -0
- data/lib/graphql/schema/member/has_path.rb +25 -0
- data/lib/graphql/schema/relay_classic_mutation.rb +3 -9
- data/lib/graphql/schema/resolver.rb +25 -5
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +21 -2
- data/lib/graphql/upgrader/member.rb +5 -0
- data/lib/graphql/version.rb +1 -1
- data/spec/dummy/Gemfile +1 -1
- data/spec/graphql/enum_type_spec.rb +5 -0
- data/spec/graphql/execution/execute_spec.rb +1 -1
- data/spec/graphql/execution/multiplex_spec.rb +28 -1
- data/spec/graphql/internal_representation/rewrite_spec.rb +2 -0
- data/spec/graphql/schema/argument_spec.rb +5 -1
- data/spec/graphql/schema/enum_spec.rb +7 -0
- data/spec/graphql/schema/enum_value_spec.rb +11 -0
- data/spec/graphql/schema/field_spec.rb +7 -0
- data/spec/graphql/schema/input_object_spec.rb +11 -0
- data/spec/graphql/schema/interface_spec.rb +6 -0
- data/spec/graphql/schema/object_spec.rb +6 -0
- data/spec/graphql/schema/relay_classic_mutation_spec.rb +71 -0
- data/spec/graphql/schema/resolver_spec.rb +72 -8
- data/spec/graphql/schema/scalar_spec.rb +6 -0
- data/spec/graphql/schema/union_spec.rb +7 -0
- data/spec/graphql/upgrader/member_spec.rb +67 -0
- data/spec/{graphql → integration/mongoid/graphql}/relay/mongo_relation_connection_spec.rb +0 -11
- data/spec/integration/mongoid/spec_helper.rb +2 -0
- data/spec/{support → integration/mongoid}/star_trek/data.rb +0 -0
- data/spec/{support → integration/mongoid}/star_trek/schema.rb +0 -0
- data/spec/{support/star_wars → integration/rails}/data.rb +1 -0
- data/spec/{support → integration/rails/generators}/base_generator_test.rb +0 -0
- data/spec/{generators → integration/rails/generators}/graphql/enum_generator_spec.rb +0 -0
- data/spec/{generators → integration/rails/generators}/graphql/install_generator_spec.rb +0 -0
- data/spec/{generators → integration/rails/generators}/graphql/interface_generator_spec.rb +0 -0
- data/spec/{generators → integration/rails/generators}/graphql/loader_generator_spec.rb +0 -0
- data/spec/{generators → integration/rails/generators}/graphql/mutation_generator_spec.rb +0 -0
- data/spec/{generators → integration/rails/generators}/graphql/object_generator_spec.rb +0 -0
- data/spec/{generators → integration/rails/generators}/graphql/union_generator_spec.rb +0 -0
- data/spec/{graphql → integration/rails/graphql}/input_object_type_spec.rb +0 -0
- data/spec/{graphql → integration/rails/graphql}/query/variables_spec.rb +0 -0
- data/spec/{graphql → integration/rails/graphql}/relay/array_connection_spec.rb +0 -0
- data/spec/{graphql → integration/rails/graphql}/relay/base_connection_spec.rb +0 -0
- data/spec/{graphql → integration/rails/graphql}/relay/connection_instrumentation_spec.rb +0 -0
- data/spec/{graphql → integration/rails/graphql}/relay/connection_resolve_spec.rb +0 -0
- data/spec/{graphql → integration/rails/graphql}/relay/connection_type_spec.rb +0 -0
- data/spec/{graphql → integration/rails/graphql}/relay/edge_spec.rb +0 -0
- data/spec/{graphql → integration/rails/graphql}/relay/mutation_spec.rb +0 -0
- data/spec/{graphql → integration/rails/graphql}/relay/node_spec.rb +0 -0
- data/spec/{graphql → integration/rails/graphql}/relay/page_info_spec.rb +0 -0
- data/spec/{graphql → integration/rails/graphql}/relay/range_add_spec.rb +0 -0
- data/spec/{graphql → integration/rails/graphql}/relay/relation_connection_spec.rb +0 -0
- data/spec/{graphql → integration/rails/graphql}/schema_spec.rb +0 -0
- data/spec/{graphql → integration/rails/graphql}/tracing/active_support_notifications_tracing_spec.rb +0 -0
- data/spec/integration/rails/spec_helper.rb +15 -0
- data/spec/spec_helper.rb +16 -39
- data/spec/support/jazz.rb +48 -0
- metadata +260 -243
- data/spec/rails_dependency_sanity_spec.rb +0 -14
@@ -14,6 +14,12 @@ describe GraphQL::Schema::Object do
|
|
14
14
|
assert object_class.respond_to?(:connection_type)
|
15
15
|
end
|
16
16
|
|
17
|
+
describe "path" do
|
18
|
+
it "is the type name" do
|
19
|
+
assert_equal "Ensemble", object_class.path
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
17
23
|
it "inherits fields and interfaces" do
|
18
24
|
new_object_class = Class.new(object_class) do
|
19
25
|
field :newField, String, null: true
|
@@ -52,6 +52,71 @@ describe GraphQL::Schema::RelayClassicMutation do
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
+
describe "loading multiple application objects" do
|
56
|
+
let(:query_str) {
|
57
|
+
<<-GRAPHQL
|
58
|
+
mutation($ids: [ID!]!) {
|
59
|
+
upvoteEnsembles(input: {ensembleIds: $ids}) {
|
60
|
+
ensembles {
|
61
|
+
id
|
62
|
+
}
|
63
|
+
}
|
64
|
+
}
|
65
|
+
GRAPHQL
|
66
|
+
}
|
67
|
+
|
68
|
+
it "loads arguments as objects of the given type and strips `_ids` suffix off argument name and appends `s`" do
|
69
|
+
res = Jazz::Schema.execute(query_str, variables: { ids: ["Ensemble/Robert Glasper Experiment", "Ensemble/Bela Fleck and the Flecktones"]})
|
70
|
+
assert_equal ["Ensemble/Robert Glasper Experiment", "Ensemble/Bela Fleck and the Flecktones"], res["data"]["upvoteEnsembles"]["ensembles"].map { |e| e["id"] }
|
71
|
+
end
|
72
|
+
|
73
|
+
it "uses the `as:` name when loading" do
|
74
|
+
as_bands_query_str = query_str.sub("upvoteEnsembles", "upvoteEnsemblesAsBands")
|
75
|
+
res = Jazz::Schema.execute(as_bands_query_str, variables: { ids: ["Ensemble/Robert Glasper Experiment", "Ensemble/Bela Fleck and the Flecktones"]})
|
76
|
+
assert_equal ["Ensemble/Robert Glasper Experiment", "Ensemble/Bela Fleck and the Flecktones"], res["data"]["upvoteEnsemblesAsBands"]["ensembles"].map { |e| e["id"] }
|
77
|
+
end
|
78
|
+
|
79
|
+
it "doesn't append `s` to argument names that already end in `s`" do
|
80
|
+
query = <<-GRAPHQL
|
81
|
+
mutation($ids: [ID!]!) {
|
82
|
+
upvoteEnsemblesIds(input: {ensemblesIds: $ids}) {
|
83
|
+
ensembles {
|
84
|
+
id
|
85
|
+
}
|
86
|
+
}
|
87
|
+
}
|
88
|
+
GRAPHQL
|
89
|
+
|
90
|
+
res = Jazz::Schema.execute(query, variables: { ids: ["Ensemble/Robert Glasper Experiment", "Ensemble/Bela Fleck and the Flecktones"]})
|
91
|
+
assert_equal ["Ensemble/Robert Glasper Experiment", "Ensemble/Bela Fleck and the Flecktones"], res["data"]["upvoteEnsemblesIds"]["ensembles"].map { |e| e["id"] }
|
92
|
+
end
|
93
|
+
|
94
|
+
it "returns an error instead when the ID resolves to nil" do
|
95
|
+
res = Jazz::Schema.execute(query_str, variables: {
|
96
|
+
ids: ["Ensemble/Nonexistant Name"],
|
97
|
+
})
|
98
|
+
assert_nil res["data"].fetch("upvoteEnsembles")
|
99
|
+
assert_equal ['No object found for `ensembleIds: "Ensemble/Nonexistant Name"`'], res["errors"].map { |e| e["message"] }
|
100
|
+
end
|
101
|
+
|
102
|
+
it "returns an error instead when the ID resolves to an object of the wrong type" do
|
103
|
+
res = Jazz::Schema.execute(query_str, variables: {
|
104
|
+
ids: ["Instrument/Organ"],
|
105
|
+
})
|
106
|
+
assert_nil res["data"].fetch("upvoteEnsembles")
|
107
|
+
assert_equal ["No object found for `ensembleIds: \"Instrument/Organ\"`"], res["errors"].map { |e| e["message"] }
|
108
|
+
end
|
109
|
+
|
110
|
+
it "raises an authorization error when the type's auth fails" do
|
111
|
+
res = Jazz::Schema.execute(query_str, variables: {
|
112
|
+
ids: ["Ensemble/Spinal Tap"],
|
113
|
+
})
|
114
|
+
assert_nil res["data"].fetch("upvoteEnsembles")
|
115
|
+
# Failed silently
|
116
|
+
refute res.key?("errors")
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
55
120
|
describe "loading application objects" do
|
56
121
|
let(:query_str) {
|
57
122
|
<<-GRAPHQL
|
@@ -70,6 +135,12 @@ describe GraphQL::Schema::RelayClassicMutation do
|
|
70
135
|
assert_equal "August Greene", res["data"]["renameEnsemble"]["ensemble"]["name"]
|
71
136
|
end
|
72
137
|
|
138
|
+
it "uses the `as:` name when loading" do
|
139
|
+
band_query_str = query_str.sub("renameEnsemble", "renameEnsembleAsBand")
|
140
|
+
res = Jazz::Schema.execute(band_query_str, variables: { id: "Ensemble/Robert Glasper Experiment", newName: "August Greene"})
|
141
|
+
assert_equal "August Greene", res["data"]["renameEnsembleAsBand"]["ensemble"]["name"]
|
142
|
+
end
|
143
|
+
|
73
144
|
it "returns an error instead when the ID resolves to nil" do
|
74
145
|
res = Jazz::Schema.execute(query_str, variables: {
|
75
146
|
id: "Ensemble/Nonexistant Name",
|
@@ -192,28 +192,45 @@ describe GraphQL::Schema::Resolver do
|
|
192
192
|
end
|
193
193
|
end
|
194
194
|
|
195
|
+
class PrepResolver9Array < BaseResolver
|
196
|
+
argument :int_ids, [ID], required: true, loads: HasValue, as: :ints
|
197
|
+
# Make sure the lazy object is resolved properly:
|
198
|
+
type [HasValue], null: false
|
199
|
+
def object_from_id(type, id, ctx)
|
200
|
+
# Make sure a lazy object is handled appropriately
|
201
|
+
LazyBlock.new {
|
202
|
+
# Make sure that the right type ends up here
|
203
|
+
id.to_i + type.graphql_name.length
|
204
|
+
}
|
205
|
+
end
|
206
|
+
|
207
|
+
def resolve(ints:)
|
208
|
+
ints.map { |int| int * 3}
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
195
212
|
class PrepResolver10 < BaseResolver
|
196
213
|
argument :int1, Integer, required: true
|
197
|
-
argument :int2, Integer, required: true
|
214
|
+
argument :int2, Integer, required: true, as: :integer_2
|
198
215
|
type Integer, null: true
|
199
|
-
def authorized?(int1:,
|
200
|
-
if int1 +
|
216
|
+
def authorized?(int1:, integer_2:)
|
217
|
+
if int1 + integer_2 > context[:max_int]
|
201
218
|
raise GraphQL::ExecutionError, "Inputs too big"
|
202
|
-
elsif context[:min_int] && (int1 +
|
219
|
+
elsif context[:min_int] && (int1 + integer_2 < context[:min_int])
|
203
220
|
false
|
204
221
|
else
|
205
222
|
true
|
206
223
|
end
|
207
224
|
end
|
208
225
|
|
209
|
-
def resolve(int1:,
|
210
|
-
int1 +
|
226
|
+
def resolve(int1:, integer_2:)
|
227
|
+
int1 + integer_2
|
211
228
|
end
|
212
229
|
end
|
213
230
|
|
214
231
|
class PrepResolver11 < PrepResolver10
|
215
|
-
def authorized?(int1:,
|
216
|
-
LazyBlock.new { super(int1: int1 * 2,
|
232
|
+
def authorized?(int1:, integer_2:)
|
233
|
+
LazyBlock.new { super(int1: int1 * 2, integer_2: integer_2) }
|
217
234
|
end
|
218
235
|
end
|
219
236
|
|
@@ -242,6 +259,17 @@ describe GraphQL::Schema::Resolver do
|
|
242
259
|
end
|
243
260
|
end
|
244
261
|
|
262
|
+
class PrepResolver14 < GraphQL::Schema::RelayClassicMutation
|
263
|
+
field :number, Integer, null: false
|
264
|
+
|
265
|
+
def authorized?
|
266
|
+
true
|
267
|
+
end
|
268
|
+
|
269
|
+
def resolve
|
270
|
+
{ number: 1 }
|
271
|
+
end
|
272
|
+
end
|
245
273
|
|
246
274
|
class Query < GraphQL::Schema::Object
|
247
275
|
class CustomField < GraphQL::Schema::Field
|
@@ -274,10 +302,12 @@ describe GraphQL::Schema::Resolver do
|
|
274
302
|
field :prep_resolver_6, resolver: PrepResolver6
|
275
303
|
field :prep_resolver_7, resolver: PrepResolver7
|
276
304
|
field :prep_resolver_9, resolver: PrepResolver9
|
305
|
+
field :prep_resolver_9_array, resolver: PrepResolver9Array
|
277
306
|
field :prep_resolver_10, resolver: PrepResolver10
|
278
307
|
field :prep_resolver_11, resolver: PrepResolver11
|
279
308
|
field :prep_resolver_12, resolver: PrepResolver12
|
280
309
|
field :prep_resolver_13, resolver: PrepResolver13
|
310
|
+
field :prep_resolver_14, resolver: PrepResolver14
|
281
311
|
end
|
282
312
|
|
283
313
|
class Schema < GraphQL::Schema
|
@@ -291,6 +321,22 @@ describe GraphQL::Schema::Resolver do
|
|
291
321
|
ResolverTest::Schema.execute(*args)
|
292
322
|
end
|
293
323
|
|
324
|
+
describe ".path" do
|
325
|
+
it "is the name" do
|
326
|
+
assert_equal "Resolver1", ResolverTest::Resolver1.path
|
327
|
+
end
|
328
|
+
|
329
|
+
it "is used for arguments and fields" do
|
330
|
+
assert_equal "Resolver1.value", ResolverTest::Resolver1.arguments["value"].path
|
331
|
+
assert_equal "PrepResolver7.int", ResolverTest::PrepResolver7.fields["int"].path
|
332
|
+
end
|
333
|
+
|
334
|
+
it "works on instances" do
|
335
|
+
r = ResolverTest::Resolver1.new(object: nil, context: nil)
|
336
|
+
assert_equal "Resolver1", r.path
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
294
340
|
it "gets initialized for each resolution" do
|
295
341
|
# State isn't shared between calls:
|
296
342
|
res = exec_query " { r1: resolver1(value: 1) r2: resolver1 }"
|
@@ -426,6 +472,11 @@ describe GraphQL::Schema::Resolver do
|
|
426
472
|
assert_equal 11, res["data"]["prepResolver10"]
|
427
473
|
end
|
428
474
|
|
475
|
+
it "uses the argument name provided in `as:`" do
|
476
|
+
res = exec_query("{ prepResolver10(int1: 5, int2: 6) }", context: { max_int: 90 })
|
477
|
+
assert_equal 11, res["data"]["prepResolver10"]
|
478
|
+
end
|
479
|
+
|
429
480
|
it "can return a lazy object" do
|
430
481
|
# This is too big because it's modified in the overridden authorized? hook:
|
431
482
|
res = exec_query("{ prepResolver11(int1: 3, int2: 5) }", context: { max_int: 9 })
|
@@ -462,6 +513,11 @@ describe GraphQL::Schema::Resolver do
|
|
462
513
|
res = exec_query(str, context: { max_int: 100, min_int: 20 })
|
463
514
|
assert_equal({ "prepResolver10" => nil, "prepResolver11" => nil }, res["data"])
|
464
515
|
end
|
516
|
+
|
517
|
+
it "works with no arguments for RelayClassicMutation" do
|
518
|
+
res = exec_query("{ prepResolver14(input: {}) { number } }")
|
519
|
+
assert_equal 1, res["data"]["prepResolver14"]["number"]
|
520
|
+
end
|
465
521
|
end
|
466
522
|
end
|
467
523
|
|
@@ -471,6 +527,14 @@ describe GraphQL::Schema::Resolver do
|
|
471
527
|
# (5 + 8) * 3
|
472
528
|
assert_equal 39, res["data"]["prepResolver9"]["value"]
|
473
529
|
end
|
530
|
+
|
531
|
+
it "supports loading array of ids" do
|
532
|
+
res = exec_query('{ prepResolver9Array(intIds: ["1", "10", "100"]) { value } }')
|
533
|
+
# (1 + 8) * 3
|
534
|
+
# (10 + 8) * 3
|
535
|
+
# (100 + 8) * 3
|
536
|
+
assert_equal [27, 54, 324], res["data"]["prepResolver9Array"].map { |v| v["value"] }
|
537
|
+
end
|
474
538
|
end
|
475
539
|
end
|
476
540
|
end
|
@@ -3,6 +3,13 @@ require "spec_helper"
|
|
3
3
|
|
4
4
|
describe GraphQL::Schema::Union do
|
5
5
|
let(:union) { Jazz::PerformingAct }
|
6
|
+
|
7
|
+
describe ".path" do
|
8
|
+
it "is the name" do
|
9
|
+
assert_equal "PerformingAct", union.path
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
6
13
|
describe "type info" do
|
7
14
|
it "has some" do
|
8
15
|
assert_equal 2, union.possible_types.size
|
@@ -292,6 +292,10 @@ RUBY
|
|
292
292
|
new = %{field :name, String, null: false}
|
293
293
|
assert_equal new, upgrade(old)
|
294
294
|
|
295
|
+
old = %{field :name, types.String.to_non_null_type}
|
296
|
+
new = %{field :name, String, null: false}
|
297
|
+
assert_equal new, upgrade(old)
|
298
|
+
|
295
299
|
old = %{field :name, !types.String, "description", method: :name_full}
|
296
300
|
new = %{field :name, String, "description", method: :name_full, null: false}
|
297
301
|
assert_equal new, upgrade(old)
|
@@ -300,6 +304,10 @@ RUBY
|
|
300
304
|
new = %{field :name, String, null: false}
|
301
305
|
assert_equal new, upgrade(old)
|
302
306
|
|
307
|
+
old = %{field :name, -> { types.String.to_non_null_type }}
|
308
|
+
new = %{field :name, String, null: false}
|
309
|
+
assert_equal new, upgrade(old)
|
310
|
+
|
303
311
|
old = %{connection :name, Name.connection_type, "names"}
|
304
312
|
new = %{field :name, Name.connection_type, "names", null: true, connection: true}
|
305
313
|
assert_equal new, upgrade(old)
|
@@ -308,10 +316,18 @@ RUBY
|
|
308
316
|
new = %{field :name, Name.connection_type, "names", null: false, connection: true}
|
309
317
|
assert_equal new, upgrade(old)
|
310
318
|
|
319
|
+
old = %{connection :name, Name.connection_type.to_non_null_type, "names"}
|
320
|
+
new = %{field :name, Name.connection_type, "names", null: false, connection: true}
|
321
|
+
assert_equal new, upgrade(old)
|
322
|
+
|
311
323
|
old = %{field :names, types[!types.String]}
|
312
324
|
new = %{field :names, [String], null: true}
|
313
325
|
assert_equal new, upgrade(old)
|
314
326
|
|
327
|
+
old = %{field :names, types[types.String.to_non_null_type]}
|
328
|
+
new = %{field :names, [String], null: true}
|
329
|
+
assert_equal new, upgrade(old)
|
330
|
+
|
315
331
|
old = %{field :names, !types[types.String]}
|
316
332
|
new = %{field :names, [String, null: true], null: false}
|
317
333
|
assert_equal new, upgrade(old)
|
@@ -341,6 +357,22 @@ RUBY
|
|
341
357
|
}
|
342
358
|
assert_equal new, upgrade(old)
|
343
359
|
|
360
|
+
old = %{
|
361
|
+
field :name, types.String.to_non_null_type do
|
362
|
+
description "abc"
|
363
|
+
end
|
364
|
+
|
365
|
+
field :name2, types.Int.to_non_null_type do
|
366
|
+
description "def"
|
367
|
+
end
|
368
|
+
}
|
369
|
+
new = %{
|
370
|
+
field :name, String, description: "abc", null: false
|
371
|
+
|
372
|
+
field :name2, Integer, description: "def", null: false
|
373
|
+
}
|
374
|
+
assert_equal new, upgrade(old)
|
375
|
+
|
344
376
|
old = %{
|
345
377
|
field :name, -> { !types.String } do
|
346
378
|
end
|
@@ -350,6 +382,15 @@ RUBY
|
|
350
382
|
}
|
351
383
|
assert_equal new, upgrade(old)
|
352
384
|
|
385
|
+
old = %{
|
386
|
+
field :name, -> { types.String.to_non_null_type } do
|
387
|
+
end
|
388
|
+
}
|
389
|
+
new = %{
|
390
|
+
field :name, String, null: false
|
391
|
+
}
|
392
|
+
assert_equal new, upgrade(old)
|
393
|
+
|
353
394
|
old = %{
|
354
395
|
field :name do
|
355
396
|
type -> { String }
|
@@ -376,6 +417,22 @@ RUBY
|
|
376
417
|
}
|
377
418
|
assert_equal new, upgrade(old)
|
378
419
|
|
420
|
+
old = %{
|
421
|
+
field :name do
|
422
|
+
type String.to_non_null_type
|
423
|
+
end
|
424
|
+
|
425
|
+
field :name2 do
|
426
|
+
type String.to_non_null_type
|
427
|
+
end
|
428
|
+
}
|
429
|
+
new = %{
|
430
|
+
field :name, String, null: false
|
431
|
+
|
432
|
+
field :name2, String, null: false
|
433
|
+
}
|
434
|
+
assert_equal new, upgrade(old)
|
435
|
+
|
379
436
|
old = %{
|
380
437
|
field :name, -> { types.String },
|
381
438
|
"newline description" do
|
@@ -396,6 +453,16 @@ RUBY
|
|
396
453
|
}
|
397
454
|
assert_equal new, upgrade(old)
|
398
455
|
|
456
|
+
old = %{
|
457
|
+
field :name, -> { types.String.to_non_null_type },
|
458
|
+
"newline description" do
|
459
|
+
end
|
460
|
+
}
|
461
|
+
new = %{
|
462
|
+
field :name, String, "newline description", null: false
|
463
|
+
}
|
464
|
+
assert_equal new, upgrade(old)
|
465
|
+
|
399
466
|
old = %{
|
400
467
|
field :name, String,
|
401
468
|
field: SomeField do
|
@@ -1,18 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
|
-
if MONGO_DETECTED
|
5
|
-
require "support/star_trek/data"
|
6
|
-
require "support/star_trek/schema"
|
7
|
-
end
|
8
|
-
|
9
4
|
describe GraphQL::Relay::MongoRelationConnection do
|
10
|
-
before do
|
11
|
-
if !MONGO_DETECTED
|
12
|
-
skip("Mongo not detected")
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
5
|
def get_names(result)
|
17
6
|
ships = result["data"]["federation"]["bases"]["edges"]
|
18
7
|
ships.map { |e| e["node"]["name"] }
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|