graphql 1.8.0.pre10 → 1.8.0.pre11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/lib/generators/graphql/install_generator.rb +14 -8
- data/lib/graphql.rb +1 -24
- data/lib/graphql/backtrace.rb +1 -1
- data/lib/graphql/deprecated_dsl.rb +2 -2
- data/lib/graphql/execution/execute.rb +6 -0
- data/lib/graphql/execution/lazy/lazy_method_map.rb +1 -1
- data/lib/graphql/introspection/base_object.rb +1 -0
- data/lib/graphql/language/document_from_schema_definition.rb +4 -1
- data/lib/graphql/language/nodes.rb +5 -2
- data/lib/graphql/language/parser.rb +288 -288
- data/lib/graphql/language/parser.y +1 -1
- data/lib/graphql/language/printer.rb +12 -2
- data/lib/graphql/non_null_type.rb +1 -1
- data/lib/graphql/query.rb +1 -1
- data/lib/graphql/query/arguments.rb +1 -1
- data/lib/graphql/query/context.rb +2 -2
- data/lib/graphql/query/null_context.rb +1 -1
- data/lib/graphql/query/result.rb +1 -1
- data/lib/graphql/query/variables.rb +21 -3
- data/lib/graphql/relay.rb +1 -0
- data/lib/graphql/relay/mongo_relation_connection.rb +40 -0
- data/lib/graphql/scalar_type.rb +14 -2
- data/lib/graphql/schema.rb +17 -1
- data/lib/graphql/schema/argument.rb +39 -7
- data/lib/graphql/schema/enum.rb +7 -0
- data/lib/graphql/schema/field.rb +145 -39
- data/lib/graphql/schema/finder.rb +4 -4
- data/lib/graphql/schema/input_object.rb +13 -2
- data/lib/graphql/schema/interface.rb +50 -16
- data/lib/graphql/schema/list.rb +28 -0
- data/lib/graphql/schema/member.rb +8 -106
- data/lib/graphql/schema/member/accepts_definition.rb +58 -24
- data/lib/graphql/schema/member/base_dsl_methods.rb +96 -0
- data/lib/graphql/schema/member/build_type.rb +15 -9
- data/lib/graphql/schema/member/cached_graphql_definition.rb +26 -0
- data/lib/graphql/schema/member/graphql_type_names.rb +21 -0
- data/lib/graphql/schema/member/has_arguments.rb +1 -1
- data/lib/graphql/schema/member/has_fields.rb +91 -8
- data/lib/graphql/schema/member/type_system_helpers.rb +34 -0
- data/lib/graphql/schema/middleware_chain.rb +5 -1
- data/lib/graphql/schema/mutation.rb +24 -12
- data/lib/graphql/schema/non_null.rb +34 -0
- data/lib/graphql/schema/object.rb +24 -11
- data/lib/graphql/schema/relay_classic_mutation.rb +14 -11
- data/lib/graphql/schema/rescue_middleware.rb +8 -7
- data/lib/graphql/schema/scalar.rb +9 -2
- data/lib/graphql/schema/union.rb +4 -0
- data/lib/graphql/static_validation/definition_dependencies.rb +1 -1
- data/lib/graphql/static_validation/literal_validator.rb +16 -4
- data/lib/graphql/static_validation/validation_context.rb +1 -1
- data/lib/graphql/subscriptions.rb +90 -16
- data/lib/graphql/upgrader/member.rb +27 -89
- data/lib/graphql/version.rb +1 -1
- data/spec/dummy/app/channels/graphql_channel.rb +1 -1
- data/spec/dummy/log/test.log +206 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/-x/-xYZjAnuuzgR79fcznLTQtSdh6AARxu8FcQ_J6p7L3U.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/13/13HiV12xyoQvT-1L39ZzLwMZxjyaGMiENmfw7f-QTIc.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/3W/3Wtf5pCWdqq0AB-iB0Y9uUNrTkruRxIEf1XFn_BETU0.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/5i/5iguGafb4hOn8262Kn8Q37ogNN9MxxQKGKNzHAzUcvI.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/8m/8mj2T6yy847Mc2Z7k3Xzh8O91hhVJt3NrPe8ASNDlIA.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/DT/DTQyMpr4ABZYQetsdRJ5A7S4jf1r3ie4FGOR7GZBNSs.cache +3 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Dq/DqJ5_yJPrP5iLlOQyTQsjAVI5FE5LCVDkED0f7GgsSo.cache +3 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F8/F8MUNRzORGFgr329fNM0xLaoWCXdv3BIalT7dsvLfjs.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/KB/KB07ZaKNC5uXJ7TjLi-WqnY6g7dq8wWp_8N3HNjBNxg.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Rw/RwDuCV-XpnCtjNkvhpJfBuxXMk0b5AD3L9eR6M-wcy0.cache +3 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/UL/ULdjhhb0bRuqmaG7XSZlFYzGYCXTDnqZuJBTWRlzqgw.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Up/UpPNgh0yYoUsyMDh5zWqe_U6qJIyTC6-dxMMAs1vvlM.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Wg/Wguh-szFGTI1gaL6npYwPekMXflugRei7F_mOyRucXg.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/X-/X-khLYMA9mqFRPg3zAi86mREDxpKl4bdKYp3uF6WHos.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/bi/BIkdhfxsezxM4q-HZ4oCNTq97WEJTigcq0tpX2cDvbY.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ff/FfxmA4CMHQZT7exx0G7NS1Wpcnny0vzp-Jhc2H36bp8.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/gE/gEiiG4GZNy_djEjK2pHm_NgA-gyhLZhdQvo0Yt96GqE.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/gn/gnA9ZSqpjccNL2m8pe_jBvY6SinXlCzXDWyop83Od8s.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/lO/lOAan3cMwCE_Hli6gsDML88xFNfn0nxPmvrSkW7eEOw.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/m1/M1pv8MJEPLXGLvS8QxVh3DSO9cI4mRt5FHFWdrvUj6o.cache +2 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/m7/m77qH7ZqH0_0SmwJbiKGDd-aLau1Dav847DC6ge46zY.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/sj/sjRjnjRB37lH2vrgtkdJ8Cz84__IJ978IuKTM7HcztI.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/um/um1JrirR4hJhK-1rE-HywlyCi5ibgxHVrReiujZBWJM.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/v4/v4fwVytD7ITcE0_GDbslZEYud8a5Okm85fV1o7SDl6g.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/v_/v_0PAQt0iipQjFP5zjgkkk9Stnpf4VzvnMv67d1Keuw.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/wd/wdT9U4MKxe1PyqNjVuCKMpCl3dxGCIRJIlwUTfh2DQU.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/xI/xIaxut_fEIhKBDqljTNwYaADK9kj3gG0ESrfHs-5_og.cache +3 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/y0/y0SJOqIx2fn1SKqOkAihsQow0trRJrSIyAswufVuoA8.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/zg/zgpzeaX-KZErHyGJ1aBH3ZusweNXMneVZule88XsIJI.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/zy/zYFltDy-8VC-uKq2BVEiJJyYXNFvVzAKuMlR3ZIYZsk.cache +0 -0
- data/spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png +0 -0
- data/spec/fixtures/upgrader/photo.original.rb +10 -0
- data/spec/fixtures/upgrader/photo.transformed.rb +12 -0
- data/spec/fixtures/upgrader/starrable.original.rb +4 -1
- data/spec/fixtures/upgrader/starrable.transformed.rb +25 -22
- data/spec/fixtures/upgrader/subscribable.transformed.rb +32 -33
- data/spec/graphql/execution_error_spec.rb +18 -0
- data/spec/graphql/introspection/schema_type_spec.rb +1 -0
- data/spec/graphql/object_type_spec.rb +2 -1
- data/spec/graphql/query/variables_spec.rb +41 -0
- data/spec/graphql/relay/mongo_relation_connection_spec.rb +474 -0
- data/spec/graphql/schema/argument_spec.rb +65 -9
- data/spec/graphql/schema/build_from_definition_spec.rb +4 -2
- data/spec/graphql/schema/enum_spec.rb +1 -1
- data/spec/graphql/schema/field_spec.rb +79 -4
- data/spec/graphql/schema/input_object_spec.rb +56 -0
- data/spec/graphql/schema/instrumentation_spec.rb +4 -3
- data/spec/graphql/schema/interface_spec.rb +40 -25
- data/spec/graphql/schema/member/accepts_definition_spec.rb +38 -11
- data/spec/graphql/schema/member/has_fields_spec.rb +129 -0
- data/spec/graphql/schema/member/type_system_helpers_spec.rb +63 -0
- data/spec/graphql/schema/mutation_spec.rb +48 -0
- data/spec/graphql/schema/object_spec.rb +34 -8
- data/spec/graphql/schema/relay_classic_mutation_spec.rb +10 -0
- data/spec/graphql/schema/rescue_middleware_spec.rb +11 -0
- data/spec/graphql/schema/scalar_spec.rb +55 -0
- data/spec/graphql/subscriptions_spec.rb +31 -4
- data/spec/graphql/upgrader/member_spec.rb +14 -6
- data/spec/spec_helper.rb +7 -0
- data/spec/support/dummy/schema.rb +8 -0
- data/spec/support/jazz.rb +89 -19
- data/spec/support/star_trek/data.rb +109 -0
- data/spec/support/star_trek/schema.rb +388 -0
- metadata +80 -7
- data/lib/graphql/schema/field/dynamic_resolve.rb +0 -70
- data/lib/graphql/schema/field/unwrapped_resolve.rb +0 -20
- data/lib/graphql/schema/member/list_type_proxy.rb +0 -25
- data/lib/graphql/schema/member/non_null_type_proxy.rb +0 -25
@@ -25,6 +25,17 @@ describe GraphQL::Schema::RescueMiddleware do
|
|
25
25
|
assert_equal(GraphQL::ExecutionError, result.class)
|
26
26
|
end
|
27
27
|
|
28
|
+
describe "rescue_from superclass" do
|
29
|
+
class ChildSpecExampleError < SpecExampleError; end
|
30
|
+
|
31
|
+
let(:error_class) { ChildSpecExampleError }
|
32
|
+
it "handles them as execution errors" do
|
33
|
+
result = middleware_chain.invoke([])
|
34
|
+
assert_equal("there was an example error: ChildSpecExampleError", result.message)
|
35
|
+
assert_equal(GraphQL::ExecutionError, result.class)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
28
39
|
describe "with multiple error classes" do
|
29
40
|
let(:error_class) { SecondSpecExampleError }
|
30
41
|
let(:rescue_middleware) do
|
@@ -36,5 +36,60 @@ describe GraphQL::Schema::Scalar do
|
|
36
36
|
assert_equal true, key_info["isSharp"]
|
37
37
|
assert_equal false, key_info["isFlat"]
|
38
38
|
end
|
39
|
+
|
40
|
+
it "can be nested JSON" do
|
41
|
+
query_str = <<-GRAPHQL
|
42
|
+
{
|
43
|
+
echoJson(input: {foo: [{bar: "baz"}]})
|
44
|
+
}
|
45
|
+
GRAPHQL
|
46
|
+
|
47
|
+
res = Jazz::Schema.execute(query_str)
|
48
|
+
assert_equal({"foo" => [{"bar" => "baz"}]}, res["data"]["echoJson"])
|
49
|
+
end
|
50
|
+
|
51
|
+
it "can be a JSON array" do
|
52
|
+
query_str = <<-GRAPHQL
|
53
|
+
{
|
54
|
+
echoFirstJson(input: [{foo: "bar"}, {baz: "boo"}])
|
55
|
+
}
|
56
|
+
GRAPHQL
|
57
|
+
|
58
|
+
res = Jazz::Schema.execute(query_str)
|
59
|
+
assert_equal({"foo" => "bar"}, res["data"]["echoFirstJson"])
|
60
|
+
end
|
61
|
+
|
62
|
+
it "can be a JSON array even if the GraphQL type is not an array" do
|
63
|
+
query_str = <<-GRAPHQL
|
64
|
+
{
|
65
|
+
echoJson(input: [{foo: "bar"}])
|
66
|
+
}
|
67
|
+
GRAPHQL
|
68
|
+
|
69
|
+
res = Jazz::Schema.execute(query_str)
|
70
|
+
assert_equal([{"foo" => "bar"}], res["data"]["echoJson"])
|
71
|
+
end
|
72
|
+
|
73
|
+
it "can be JSON with a nested enum" do
|
74
|
+
query_str = <<-GRAPHQL
|
75
|
+
{
|
76
|
+
echoJson(input: [{foo: WOODWIND}])
|
77
|
+
}
|
78
|
+
GRAPHQL
|
79
|
+
|
80
|
+
res = Jazz::Schema.execute(query_str)
|
81
|
+
assert_equal([{"foo" => "WOODWIND"}], res["data"]["echoJson"])
|
82
|
+
end
|
83
|
+
|
84
|
+
it "cannot be JSON with a nested variable" do
|
85
|
+
query_str = <<-GRAPHQL
|
86
|
+
{
|
87
|
+
echoJson(input: [{foo: $var}])
|
88
|
+
}
|
89
|
+
GRAPHQL
|
90
|
+
|
91
|
+
res = Jazz::Schema.execute(query_str)
|
92
|
+
assert_includes(res["errors"][0]["message"], "Argument 'input' on Field 'echoJson' has an invalid value")
|
93
|
+
end
|
39
94
|
end
|
40
95
|
end
|
@@ -192,10 +192,10 @@ describe GraphQL::Subscriptions do
|
|
192
192
|
|
193
193
|
# Application stuff happens.
|
194
194
|
# The application signals graphql via `subscriptions.trigger`:
|
195
|
-
schema.subscriptions.trigger(
|
195
|
+
schema.subscriptions.trigger(:payload, {"id" => "100"}, root_object.payload)
|
196
196
|
schema.subscriptions.trigger("payload", {"id" => "200"}, root_object.payload)
|
197
197
|
# Symobls are OK too
|
198
|
-
schema.subscriptions.trigger(
|
198
|
+
schema.subscriptions.trigger(:payload, {:id => "100"}, root_object.payload)
|
199
199
|
schema.subscriptions.trigger("payload", {"id" => "300"}, nil)
|
200
200
|
|
201
201
|
# Let's see what GraphQL sent over the wire:
|
@@ -267,8 +267,8 @@ describe GraphQL::Subscriptions do
|
|
267
267
|
schema.subscriptions.trigger("event", { "stream" => {"type" => "ONE", "userId" => "3"} }, OpenStruct.new(str: "", int: 2))
|
268
268
|
# This is a non-trigger
|
269
269
|
schema.subscriptions.trigger("event", { "stream" => {"userId" => "3", "type" => "TWO"} }, OpenStruct.new(str: "", int: 3))
|
270
|
-
# These get default value of ONE
|
271
|
-
schema.subscriptions.trigger("event", {
|
270
|
+
# These get default value of ONE (underscored / symbols are ok)
|
271
|
+
schema.subscriptions.trigger("event", { stream: { user_id: "3"} }, OpenStruct.new(str: "", int: 4))
|
272
272
|
# Trigger with null updates subscriptionss to null
|
273
273
|
schema.subscriptions.trigger("event", { "stream" => {"userId" => 3, "type" => nil} }, OpenStruct.new(str: "", int: 5))
|
274
274
|
|
@@ -391,4 +391,31 @@ describe GraphQL::Subscriptions do
|
|
391
391
|
refute_equal schema.subscriptions.build_id, schema.subscriptions.build_id
|
392
392
|
end
|
393
393
|
end
|
394
|
+
|
395
|
+
describe ".trigger" do
|
396
|
+
it "raises when event name is not found" do
|
397
|
+
err = assert_raises(GraphQL::Subscriptions::InvalidTriggerError) do
|
398
|
+
schema.subscriptions.trigger(:nonsense_field, {}, nil)
|
399
|
+
end
|
400
|
+
|
401
|
+
assert_includes err.message, "trigger: nonsense_field"
|
402
|
+
assert_includes err.message, "Subscription.nonsenseField"
|
403
|
+
end
|
404
|
+
|
405
|
+
it "raises when argument is not found" do
|
406
|
+
err = assert_raises(GraphQL::Subscriptions::InvalidTriggerError) do
|
407
|
+
schema.subscriptions.trigger(:event, { scream: {"userId" => "😱"} }, nil)
|
408
|
+
end
|
409
|
+
|
410
|
+
assert_includes err.message, "arguments: scream"
|
411
|
+
assert_includes err.message, "arguments of Subscription.event"
|
412
|
+
|
413
|
+
err = assert_raises(GraphQL::Subscriptions::InvalidTriggerError) do
|
414
|
+
schema.subscriptions.trigger(:event, { stream: { user_id_number: "😱"} }, nil)
|
415
|
+
end
|
416
|
+
|
417
|
+
assert_includes err.message, "arguments: user_id_number"
|
418
|
+
assert_includes err.message, "arguments of StreamInput"
|
419
|
+
end
|
420
|
+
end
|
394
421
|
end
|
@@ -111,10 +111,12 @@ describe GraphQL::Upgrader::Member do
|
|
111
111
|
end
|
112
112
|
}
|
113
113
|
new = %{
|
114
|
-
|
114
|
+
module UserInterface
|
115
|
+
include Types::BaseInterface
|
115
116
|
graphql_name "User"
|
116
117
|
end
|
117
118
|
}
|
119
|
+
|
118
120
|
assert_equal new, upgrade(old)
|
119
121
|
|
120
122
|
old = %{
|
@@ -139,10 +141,16 @@ describe GraphQL::Upgrader::Member do
|
|
139
141
|
end}
|
140
142
|
assert_equal new, upgrade(old)
|
141
143
|
|
142
|
-
old =
|
143
|
-
|
144
|
-
|
145
|
-
|
144
|
+
old = <<-RUBY
|
145
|
+
UserInterface = GraphQL::InterfaceType.define do
|
146
|
+
end
|
147
|
+
RUBY
|
148
|
+
new = <<-RUBY
|
149
|
+
module UserInterface
|
150
|
+
include Types::BaseInterface
|
151
|
+
end
|
152
|
+
RUBY
|
153
|
+
|
146
154
|
assert_equal new, upgrade(old)
|
147
155
|
|
148
156
|
old = %{UserUnion = GraphQL::UnionType.define do
|
@@ -474,7 +482,7 @@ describe GraphQL::Upgrader::Member do
|
|
474
482
|
# Replace the default one with a custom one:
|
475
483
|
type_transforms = GraphQL::Upgrader::Member::DEFAULT_TYPE_TRANSFORMS.map { |t|
|
476
484
|
if t == GraphQL::Upgrader::TypeDefineToClassTransform
|
477
|
-
GraphQL::Upgrader::TypeDefineToClassTransform.new(base_class_pattern: "Platform::\\
|
485
|
+
GraphQL::Upgrader::TypeDefineToClassTransform.new(base_class_pattern: "Platform::\\3s::Base")
|
478
486
|
else
|
479
487
|
t
|
480
488
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -16,6 +16,7 @@ if rails_should_be_installed?
|
|
16
16
|
require "jdbc/sqlite3" if RUBY_ENGINE == 'jruby'
|
17
17
|
require "sqlite3" if RUBY_ENGINE == 'ruby'
|
18
18
|
require "pg" if RUBY_ENGINE == 'ruby'
|
19
|
+
require "mongoid" if RUBY_ENGINE == 'ruby'
|
19
20
|
require "sequel"
|
20
21
|
end
|
21
22
|
|
@@ -40,6 +41,7 @@ assign_metadata_key = ->(target, key, value) { target.metadata[key] = value }
|
|
40
41
|
assign_metadata_flag = ->(target, flag) { target.metadata[flag] = true }
|
41
42
|
GraphQL::Schema.accepts_definitions(set_metadata: assign_metadata_key)
|
42
43
|
GraphQL::BaseType.accepts_definitions(metadata: assign_metadata_key)
|
44
|
+
GraphQL::BaseType.accepts_definitions(metadata2: assign_metadata_key)
|
43
45
|
GraphQL::Field.accepts_definitions(metadata: assign_metadata_key)
|
44
46
|
GraphQL::Argument.accepts_definitions(metadata: assign_metadata_key)
|
45
47
|
GraphQL::Argument.accepts_definitions(metadata_flag: assign_metadata_flag)
|
@@ -62,11 +64,16 @@ NO_OP_RESOLVE_TYPE = ->(type, obj, ctx) {
|
|
62
64
|
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each do |f|
|
63
65
|
unless rails_should_be_installed?
|
64
66
|
next if f.end_with?('star_wars/data.rb')
|
67
|
+
next if f.end_with?('star_trek/data.rb')
|
65
68
|
next if f.end_with?('base_generator_test.rb')
|
66
69
|
end
|
67
70
|
require f
|
68
71
|
end
|
69
72
|
|
73
|
+
def star_trek_query(string, variables={}, context: {})
|
74
|
+
StarTrek::Schema.execute(string, variables: variables, context: context)
|
75
|
+
end
|
76
|
+
|
70
77
|
def star_wars_query(string, variables={}, context: {})
|
71
78
|
StarWars::Schema.execute(string, variables: variables, context: context)
|
72
79
|
end
|
@@ -366,6 +366,14 @@ module Dummy
|
|
366
366
|
}
|
367
367
|
end
|
368
368
|
|
369
|
+
field :multipleErrorsOnNonNullableField do
|
370
|
+
type !GraphQL::STRING_TYPE
|
371
|
+
resolve ->(t, a, c) {
|
372
|
+
[GraphQL::ExecutionError.new("This is an error message for some error."),
|
373
|
+
GraphQL::ExecutionError.new("This is another error message for a different error.")]
|
374
|
+
}
|
375
|
+
end
|
376
|
+
|
369
377
|
field :executionErrorWithOptions do
|
370
378
|
type GraphQL::INT_TYPE
|
371
379
|
resolve ->(t, a, c) {
|
data/spec/support/jazz.rb
CHANGED
@@ -31,6 +31,7 @@ module Jazz
|
|
31
31
|
],
|
32
32
|
"Ensemble" => [
|
33
33
|
Models::Ensemble.new("Bela Fleck and the Flecktones"),
|
34
|
+
Models::Ensemble.new("Robert Glasper Experiment"),
|
34
35
|
],
|
35
36
|
"Musician" => [
|
36
37
|
Models::Musician.new("Herbie Hancock", Models::Key.from_notation("B♭")),
|
@@ -64,15 +65,13 @@ module Jazz
|
|
64
65
|
super(*args, **options, &block)
|
65
66
|
end
|
66
67
|
|
67
|
-
def
|
68
|
-
|
69
|
-
if @upcase
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
}
|
68
|
+
def resolve_field(*)
|
69
|
+
result = super
|
70
|
+
if @upcase && result
|
71
|
+
result.upcase
|
72
|
+
else
|
73
|
+
result
|
74
74
|
end
|
75
|
-
field_defn
|
76
75
|
end
|
77
76
|
end
|
78
77
|
|
@@ -99,9 +98,17 @@ module Jazz
|
|
99
98
|
end
|
100
99
|
end
|
101
100
|
|
102
|
-
|
101
|
+
module BaseInterface
|
102
|
+
include GraphQL::Schema::Interface
|
103
103
|
# Use this overridden field class
|
104
104
|
field_class BaseField
|
105
|
+
|
106
|
+
# These methods are available to child interfaces
|
107
|
+
definition_methods do
|
108
|
+
def upcased_field(*args, **kwargs, &block)
|
109
|
+
field(*args, upcase: true, **kwargs, &block)
|
110
|
+
end
|
111
|
+
end
|
105
112
|
end
|
106
113
|
|
107
114
|
class BaseEnumValue < GraphQL::Schema::EnumValue
|
@@ -123,15 +130,14 @@ module Jazz
|
|
123
130
|
|
124
131
|
# Some arbitrary global ID scheme
|
125
132
|
# *Type suffix is removed automatically
|
126
|
-
|
133
|
+
module GloballyIdentifiableType
|
134
|
+
include BaseInterface
|
127
135
|
description "A fetchable object in the system"
|
128
136
|
field :id, ID, "A unique identifier for this object", null: false
|
129
|
-
|
137
|
+
upcased_field :upcased_id, ID, null: false, method: :id # upcase: true added by helper
|
130
138
|
|
131
|
-
|
132
|
-
|
133
|
-
GloballyIdentifiableType.to_id(@object)
|
134
|
-
end
|
139
|
+
def id
|
140
|
+
GloballyIdentifiableType.to_id(@object)
|
135
141
|
end
|
136
142
|
|
137
143
|
def self.to_id(object)
|
@@ -160,15 +166,25 @@ module Jazz
|
|
160
166
|
end
|
161
167
|
end
|
162
168
|
|
169
|
+
module HasMusicians
|
170
|
+
include BaseInterface
|
171
|
+
field :musicians, "[Jazz::Musician]", null: false
|
172
|
+
end
|
173
|
+
|
174
|
+
|
163
175
|
# Here's a new-style GraphQL type definition
|
164
176
|
class Ensemble < ObjectWithUpcasedName
|
165
|
-
|
177
|
+
# Test string type names
|
178
|
+
# This method should override inherited one
|
179
|
+
field :name, "String", null: false, method: :overridden_name
|
180
|
+
implements GloballyIdentifiableType, NamedEntity, HasMusicians
|
166
181
|
description "A group of musicians playing together"
|
167
182
|
config :config, :configged
|
168
|
-
# Test string type names:
|
169
|
-
field :name, "String", null: false
|
170
|
-
field :musicians, "[Jazz::Musician]", null: false
|
171
183
|
field :formed_at, String, null: true, hash_key: "formedAtDate"
|
184
|
+
|
185
|
+
def overridden_name
|
186
|
+
@object.name.sub("Robert Glasper", "ROBERT GLASPER")
|
187
|
+
end
|
172
188
|
end
|
173
189
|
|
174
190
|
class Family < BaseEnum
|
@@ -212,6 +228,16 @@ module Jazz
|
|
212
228
|
end
|
213
229
|
end
|
214
230
|
|
231
|
+
class RawJson < GraphQL::Schema::Scalar
|
232
|
+
def self.coerce_input(val, ctx)
|
233
|
+
val
|
234
|
+
end
|
235
|
+
|
236
|
+
def self.coerce_result(val, ctx)
|
237
|
+
val
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
215
241
|
class Musician < BaseObject
|
216
242
|
implements GloballyIdentifiableType
|
217
243
|
implements NamedEntity
|
@@ -279,6 +305,10 @@ module Jazz
|
|
279
305
|
end
|
280
306
|
end
|
281
307
|
|
308
|
+
class HashKeyTest < BaseObject
|
309
|
+
field :falsey, Boolean, null: false
|
310
|
+
end
|
311
|
+
|
282
312
|
# Another new-style definition, with method overrides
|
283
313
|
class Query < BaseObject
|
284
314
|
field :ensembles, [Ensemble], null: false
|
@@ -300,6 +330,14 @@ module Jazz
|
|
300
330
|
field :inspect_context, [String], null: false
|
301
331
|
field :hashyEnsemble, Ensemble, null: false
|
302
332
|
|
333
|
+
field :echo_json, RawJson, null: false do
|
334
|
+
argument :input, RawJson, required: true
|
335
|
+
end
|
336
|
+
|
337
|
+
field :echo_first_json, RawJson, null: false do
|
338
|
+
argument :input, [RawJson], required: true
|
339
|
+
end
|
340
|
+
|
303
341
|
def ensembles
|
304
342
|
Models.data["Ensemble"]
|
305
343
|
end
|
@@ -358,6 +396,24 @@ module Jazz
|
|
358
396
|
"formedAtDate" => "May 5, 1965",
|
359
397
|
}
|
360
398
|
end
|
399
|
+
|
400
|
+
def echo_json(input:)
|
401
|
+
input
|
402
|
+
end
|
403
|
+
|
404
|
+
def echo_first_json(input:)
|
405
|
+
input.first
|
406
|
+
end
|
407
|
+
|
408
|
+
field :hash_by_string, HashKeyTest, null: false
|
409
|
+
field :hash_by_sym, HashKeyTest, null: false
|
410
|
+
def hash_by_string
|
411
|
+
{ "falsey" => false }
|
412
|
+
end
|
413
|
+
|
414
|
+
def hash_by_sym
|
415
|
+
{ falsey: false }
|
416
|
+
end
|
361
417
|
end
|
362
418
|
|
363
419
|
class EnsembleInput < GraphQL::Schema::InputObject
|
@@ -365,6 +421,7 @@ module Jazz
|
|
365
421
|
end
|
366
422
|
|
367
423
|
class AddInstrument < GraphQL::Schema::Mutation
|
424
|
+
null true
|
368
425
|
description "Register a new musical instrument in the database"
|
369
426
|
|
370
427
|
argument :name, String, required: true
|
@@ -396,6 +453,19 @@ module Jazz
|
|
396
453
|
Models.data["Ensemble"] << ens
|
397
454
|
ens
|
398
455
|
end
|
456
|
+
|
457
|
+
field :prepare_input, Integer, null: false do
|
458
|
+
argument :input, Integer, required: true, prepare: :square, as: :squared_input
|
459
|
+
end
|
460
|
+
|
461
|
+
def prepare_input(squared_input:)
|
462
|
+
# Test that `square` is called
|
463
|
+
squared_input
|
464
|
+
end
|
465
|
+
|
466
|
+
def square(value)
|
467
|
+
value ** 2
|
468
|
+
end
|
399
469
|
end
|
400
470
|
|
401
471
|
class MetadataPlugin
|
@@ -0,0 +1,109 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
module StarTrek
|
5
|
+
names = [
|
6
|
+
'USS Enterprise',
|
7
|
+
'USS Excelsior',
|
8
|
+
'USS Reliant',
|
9
|
+
'IKS Koraga',
|
10
|
+
'IKS Kronos One',
|
11
|
+
'IRW Khazara',
|
12
|
+
'IRW Praetus',
|
13
|
+
]
|
14
|
+
|
15
|
+
MONGOID_CONFIG = {
|
16
|
+
clients: {
|
17
|
+
default: {
|
18
|
+
database: 'graphql_ruby_test',
|
19
|
+
hosts: ['localhost:27017']
|
20
|
+
}
|
21
|
+
},
|
22
|
+
sessions: {
|
23
|
+
default: {
|
24
|
+
database: 'graphql_ruby_test',
|
25
|
+
hosts: ['localhost:27017']
|
26
|
+
}
|
27
|
+
}
|
28
|
+
}.freeze
|
29
|
+
|
30
|
+
def db_name
|
31
|
+
MONGOID_CONFIG[:clients][:default][:database]
|
32
|
+
end
|
33
|
+
module_function :db_name
|
34
|
+
|
35
|
+
# Set up "Bases" in MongoDB
|
36
|
+
Mongoid.load_configuration(MONGOID_CONFIG)
|
37
|
+
|
38
|
+
class Base
|
39
|
+
include Mongoid::Document
|
40
|
+
field :name, type: String
|
41
|
+
field :sector, type: String
|
42
|
+
field :faction_id, type: Integer
|
43
|
+
end
|
44
|
+
|
45
|
+
Base.collection.drop
|
46
|
+
Base.create!(name: "Deep Space Station K-7", sector: "Mempa", faction_id: 1)
|
47
|
+
Base.create!(name: "Regula I", sector: "Mutara", faction_id: 1)
|
48
|
+
Base.create!(name: "Deep Space Nine", sector: "Bajoran", faction_id: 1)
|
49
|
+
Base.create!(name: "Firebase P'ok", sector: nil, faction_id: 2)
|
50
|
+
Base.create!(name: "Ganalda Space Station", sector: "Archanis", faction_id: 2)
|
51
|
+
Base.create!(name: "Rh'Ihho Station", sector: "Rator", faction_id: 3)
|
52
|
+
|
53
|
+
class FactionRecord
|
54
|
+
attr_reader :id, :name, :ships, :bases, :bases_clone
|
55
|
+
def initialize(id:, name:, ships:, bases:, bases_clone:)
|
56
|
+
@id = id
|
57
|
+
@name = name
|
58
|
+
@ships = ships
|
59
|
+
@bases = bases
|
60
|
+
@bases_clone = bases_clone
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
federation = FactionRecord.new({
|
65
|
+
id: '1',
|
66
|
+
name: 'United Federation of Planets',
|
67
|
+
ships: ['1', '2', '3'],
|
68
|
+
bases: Base.where(faction_id: 1),
|
69
|
+
bases_clone: Base.where(faction_id: 1),
|
70
|
+
})
|
71
|
+
|
72
|
+
klingon = FactionRecord.new({
|
73
|
+
id: '2',
|
74
|
+
name: 'Klingon Empire',
|
75
|
+
ships: ['4', '5'],
|
76
|
+
bases: Base.where(faction_id: 2),
|
77
|
+
bases_clone: Base.where(faction_id: 2),
|
78
|
+
})
|
79
|
+
|
80
|
+
romulan = FactionRecord.new({
|
81
|
+
id: '2',
|
82
|
+
name: 'Romulan Star Empire',
|
83
|
+
ships: ['6', '7'],
|
84
|
+
bases: Base.where(faction_id: 3),
|
85
|
+
bases_clone: Base.where(faction_id: 3),
|
86
|
+
})
|
87
|
+
|
88
|
+
DATA = {
|
89
|
+
"Faction" => {
|
90
|
+
"1" => federation,
|
91
|
+
"2" => klingon,
|
92
|
+
"3" => romulan,
|
93
|
+
},
|
94
|
+
"Ship" => names.each_with_index.reduce({}) do |memo, (name, idx)|
|
95
|
+
id = (idx + 1).to_s
|
96
|
+
memo[id] = OpenStruct.new(name: name, id: id)
|
97
|
+
memo
|
98
|
+
end,
|
99
|
+
"Base" => Hash.new { |h, k| h[k] = Base.find(k) }
|
100
|
+
}
|
101
|
+
|
102
|
+
def DATA.create_ship(name, faction_id)
|
103
|
+
new_id = (self["Ship"].keys.map(&:to_i).max + 1).to_s
|
104
|
+
new_ship = OpenStruct.new(id: new_id, name: name)
|
105
|
+
self["Ship"][new_id] = new_ship
|
106
|
+
self["Faction"][faction_id].ships << new_id
|
107
|
+
new_ship
|
108
|
+
end
|
109
|
+
end
|