graphql 1.11.8 → 1.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/generators/graphql/install_generator.rb +5 -5
- data/lib/generators/graphql/relay_generator.rb +63 -0
- data/lib/generators/graphql/templates/base_connection.erb +8 -0
- data/lib/generators/graphql/templates/base_edge.erb +8 -0
- data/lib/generators/graphql/templates/node_type.erb +9 -0
- data/lib/generators/graphql/templates/object.erb +1 -1
- data/lib/generators/graphql/templates/query_type.erb +1 -3
- data/lib/generators/graphql/templates/schema.erb +8 -35
- data/lib/graphql.rb +38 -4
- data/lib/graphql/analysis/analyze_query.rb +7 -0
- data/lib/graphql/analysis/ast.rb +11 -2
- data/lib/graphql/analysis/ast/visitor.rb +9 -1
- data/lib/graphql/backtrace.rb +28 -19
- data/lib/graphql/backtrace/legacy_tracer.rb +56 -0
- data/lib/graphql/backtrace/table.rb +22 -2
- data/lib/graphql/backtrace/tracer.rb +40 -9
- data/lib/graphql/backwards_compatibility.rb +1 -0
- data/lib/graphql/compatibility/execution_specification.rb +1 -0
- data/lib/graphql/compatibility/lazy_execution_specification.rb +2 -0
- data/lib/graphql/compatibility/query_parser_specification.rb +2 -0
- data/lib/graphql/compatibility/schema_parser_specification.rb +2 -0
- data/lib/graphql/dataloader.rb +197 -0
- data/lib/graphql/dataloader/null_dataloader.rb +21 -0
- data/lib/graphql/dataloader/request.rb +24 -0
- data/lib/graphql/dataloader/request_all.rb +22 -0
- data/lib/graphql/dataloader/source.rb +93 -0
- data/lib/graphql/define/assign_global_id_field.rb +1 -1
- data/lib/graphql/define/instance_definable.rb +32 -2
- data/lib/graphql/define/type_definer.rb +5 -5
- data/lib/graphql/deprecated_dsl.rb +5 -0
- data/lib/graphql/enum_type.rb +2 -0
- data/lib/graphql/execution/errors.rb +4 -0
- data/lib/graphql/execution/execute.rb +7 -0
- data/lib/graphql/execution/interpreter.rb +10 -6
- data/lib/graphql/execution/interpreter/arguments.rb +51 -14
- data/lib/graphql/execution/interpreter/handles_raw_value.rb +0 -7
- data/lib/graphql/execution/interpreter/runtime.rb +210 -124
- data/lib/graphql/execution/multiplex.rb +20 -6
- data/lib/graphql/function.rb +4 -0
- data/lib/graphql/input_object_type.rb +2 -0
- data/lib/graphql/interface_type.rb +3 -1
- data/lib/graphql/language/document_from_schema_definition.rb +50 -23
- data/lib/graphql/object_type.rb +2 -0
- data/lib/graphql/pagination/connection.rb +5 -1
- data/lib/graphql/pagination/connections.rb +6 -16
- data/lib/graphql/query.rb +2 -0
- data/lib/graphql/query/context.rb +4 -0
- data/lib/graphql/query/serial_execution.rb +1 -0
- data/lib/graphql/relay/base_connection.rb +7 -0
- data/lib/graphql/relay/connection_instrumentation.rb +4 -4
- data/lib/graphql/relay/connection_type.rb +1 -1
- data/lib/graphql/relay/mutation.rb +1 -0
- data/lib/graphql/relay/node.rb +3 -0
- data/lib/graphql/relay/type_extensions.rb +2 -0
- data/lib/graphql/scalar_type.rb +2 -0
- data/lib/graphql/schema.rb +69 -32
- data/lib/graphql/schema/argument.rb +25 -7
- data/lib/graphql/schema/build_from_definition.rb +139 -51
- data/lib/graphql/schema/directive.rb +76 -0
- data/lib/graphql/schema/directive/flagged.rb +57 -0
- data/lib/graphql/schema/enum.rb +3 -0
- data/lib/graphql/schema/enum_value.rb +12 -6
- data/lib/graphql/schema/field.rb +28 -9
- data/lib/graphql/schema/field/connection_extension.rb +3 -2
- data/lib/graphql/schema/input_object.rb +33 -22
- data/lib/graphql/schema/interface.rb +1 -0
- data/lib/graphql/schema/member.rb +4 -0
- data/lib/graphql/schema/member/base_dsl_methods.rb +1 -0
- data/lib/graphql/schema/member/build_type.rb +3 -3
- data/lib/graphql/schema/member/has_arguments.rb +24 -6
- data/lib/graphql/schema/member/has_deprecation_reason.rb +25 -0
- data/lib/graphql/schema/member/has_directives.rb +98 -0
- data/lib/graphql/schema/member/has_validators.rb +31 -0
- data/lib/graphql/schema/member/type_system_helpers.rb +1 -1
- data/lib/graphql/schema/object.rb +11 -0
- data/lib/graphql/schema/printer.rb +5 -4
- data/lib/graphql/schema/resolver.rb +7 -0
- data/lib/graphql/schema/resolver/has_payload_type.rb +2 -0
- data/lib/graphql/schema/subscription.rb +19 -1
- data/lib/graphql/schema/timeout_middleware.rb +2 -0
- data/lib/graphql/schema/validation.rb +2 -0
- data/lib/graphql/schema/validator.rb +163 -0
- data/lib/graphql/schema/validator/exclusion_validator.rb +31 -0
- data/lib/graphql/schema/validator/format_validator.rb +49 -0
- data/lib/graphql/schema/validator/inclusion_validator.rb +33 -0
- data/lib/graphql/schema/validator/length_validator.rb +57 -0
- data/lib/graphql/schema/validator/numericality_validator.rb +71 -0
- data/lib/graphql/schema/validator/required_validator.rb +68 -0
- data/lib/graphql/static_validation/validator.rb +2 -0
- data/lib/graphql/subscriptions.rb +17 -20
- data/lib/graphql/tracing.rb +2 -2
- data/lib/graphql/tracing/appoptics_tracing.rb +3 -1
- data/lib/graphql/tracing/platform_tracing.rb +3 -1
- data/lib/graphql/tracing/skylight_tracing.rb +1 -1
- data/lib/graphql/types/relay.rb +11 -3
- data/lib/graphql/types/relay/base_connection.rb +2 -92
- data/lib/graphql/types/relay/base_edge.rb +2 -35
- data/lib/graphql/types/relay/connection_behaviors.rb +123 -0
- data/lib/graphql/types/relay/default_relay.rb +27 -0
- data/lib/graphql/types/relay/edge_behaviors.rb +42 -0
- data/lib/graphql/types/relay/has_node_field.rb +41 -0
- data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
- data/lib/graphql/types/relay/node.rb +2 -4
- data/lib/graphql/types/relay/node_behaviors.rb +15 -0
- data/lib/graphql/types/relay/node_field.rb +1 -19
- data/lib/graphql/types/relay/nodes_field.rb +1 -19
- data/lib/graphql/types/relay/page_info.rb +2 -14
- data/lib/graphql/types/relay/page_info_behaviors.rb +25 -0
- data/lib/graphql/union_type.rb +2 -0
- data/lib/graphql/upgrader/member.rb +1 -0
- data/lib/graphql/upgrader/schema.rb +1 -0
- data/lib/graphql/version.rb +1 -1
- metadata +34 -9
- data/lib/graphql/types/relay/base_field.rb +0 -22
- data/lib/graphql/types/relay/base_interface.rb +0 -29
- data/lib/graphql/types/relay/base_object.rb +0 -26
@@ -27,98 +27,8 @@ module GraphQL
|
|
27
27
|
# end
|
28
28
|
#
|
29
29
|
# @see Relay::BaseEdge for edge types
|
30
|
-
class BaseConnection <
|
31
|
-
|
32
|
-
def_delegators :@object, :cursor_from_node, :parent
|
33
|
-
|
34
|
-
class << self
|
35
|
-
# @return [Class]
|
36
|
-
attr_reader :node_type
|
37
|
-
|
38
|
-
# @return [Class]
|
39
|
-
attr_reader :edge_class
|
40
|
-
|
41
|
-
# Configure this connection to return `edges` and `nodes` based on `edge_type_class`.
|
42
|
-
#
|
43
|
-
# This method will use the inputs to create:
|
44
|
-
# - `edges` field
|
45
|
-
# - `nodes` field
|
46
|
-
# - description
|
47
|
-
#
|
48
|
-
# It's called when you subclass this base connection, trying to use the
|
49
|
-
# class name to set defaults. You can call it again in the class definition
|
50
|
-
# to override the default (or provide a value, if the default lookup failed).
|
51
|
-
def edge_type(edge_type_class, edge_class: GraphQL::Relay::Edge, node_type: edge_type_class.node_type, nodes_field: true, node_nullable: true)
|
52
|
-
# Set this connection's graphql name
|
53
|
-
node_type_name = node_type.graphql_name
|
54
|
-
|
55
|
-
@node_type = node_type
|
56
|
-
@edge_type = edge_type_class
|
57
|
-
@edge_class = edge_class
|
58
|
-
|
59
|
-
field :edges, [edge_type_class, null: true],
|
60
|
-
null: true,
|
61
|
-
description: "A list of edges.",
|
62
|
-
edge_class: edge_class
|
63
|
-
|
64
|
-
define_nodes_field(node_nullable) if nodes_field
|
65
|
-
|
66
|
-
description("The connection type for #{node_type_name}.")
|
67
|
-
end
|
68
|
-
|
69
|
-
# Filter this list according to the way its node type would scope them
|
70
|
-
def scope_items(items, context)
|
71
|
-
node_type.scope_items(items, context)
|
72
|
-
end
|
73
|
-
|
74
|
-
# Add the shortcut `nodes` field to this connection and its subclasses
|
75
|
-
def nodes_field
|
76
|
-
define_nodes_field
|
77
|
-
end
|
78
|
-
|
79
|
-
def authorized?(obj, ctx)
|
80
|
-
true # Let nodes be filtered out
|
81
|
-
end
|
82
|
-
|
83
|
-
def accessible?(ctx)
|
84
|
-
node_type.accessible?(ctx)
|
85
|
-
end
|
86
|
-
|
87
|
-
def visible?(ctx)
|
88
|
-
node_type.visible?(ctx)
|
89
|
-
end
|
90
|
-
|
91
|
-
private
|
92
|
-
|
93
|
-
def define_nodes_field(nullable = true)
|
94
|
-
type = nullable ? [@node_type, null: true] : [@node_type]
|
95
|
-
field :nodes, type,
|
96
|
-
null: nullable,
|
97
|
-
description: "A list of nodes.",
|
98
|
-
connection: false
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
field :page_info, GraphQL::Types::Relay::PageInfo, null: false, description: "Information to aid in pagination."
|
103
|
-
|
104
|
-
# By default this calls through to the ConnectionWrapper's edge nodes method,
|
105
|
-
# but sometimes you need to override it to support the `nodes` field
|
106
|
-
def nodes
|
107
|
-
@object.edge_nodes
|
108
|
-
end
|
109
|
-
|
110
|
-
def edges
|
111
|
-
if @object.is_a?(GraphQL::Pagination::Connection)
|
112
|
-
@object.edges
|
113
|
-
elsif context.interpreter?
|
114
|
-
context.schema.after_lazy(object.edge_nodes) do |nodes|
|
115
|
-
nodes.map { |n| self.class.edge_class.new(n, object) }
|
116
|
-
end
|
117
|
-
else
|
118
|
-
# This is done by edges_instrumentation
|
119
|
-
@object.edge_nodes
|
120
|
-
end
|
121
|
-
end
|
30
|
+
class BaseConnection < Schema::Object
|
31
|
+
include ConnectionBehaviors
|
122
32
|
end
|
123
33
|
end
|
124
34
|
end
|
@@ -21,41 +21,8 @@ module GraphQL
|
|
21
21
|
# end
|
22
22
|
#
|
23
23
|
# @see {Relay::BaseConnection} for connection types
|
24
|
-
class BaseEdge <
|
25
|
-
|
26
|
-
|
27
|
-
class << self
|
28
|
-
# Get or set the Object type that this edge wraps.
|
29
|
-
#
|
30
|
-
# @param node_type [Class] A `Schema::Object` subclass
|
31
|
-
# @param null [Boolean]
|
32
|
-
def node_type(node_type = nil, null: true)
|
33
|
-
if node_type
|
34
|
-
@node_type = node_type
|
35
|
-
# Add a default `node` field
|
36
|
-
field :node, node_type, null: null, description: "The item at the end of the edge.",
|
37
|
-
connection: false
|
38
|
-
end
|
39
|
-
@node_type
|
40
|
-
end
|
41
|
-
|
42
|
-
def authorized?(obj, ctx)
|
43
|
-
true
|
44
|
-
end
|
45
|
-
|
46
|
-
def accessible?(ctx)
|
47
|
-
node_type.accessible?(ctx)
|
48
|
-
end
|
49
|
-
|
50
|
-
def visible?(ctx)
|
51
|
-
node_type.visible?(ctx)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
|
56
|
-
field :cursor, String,
|
57
|
-
null: false,
|
58
|
-
description: "A cursor for use in pagination."
|
24
|
+
class BaseEdge < GraphQL::Schema::Object
|
25
|
+
include Types::Relay::EdgeBehaviors
|
59
26
|
end
|
60
27
|
end
|
61
28
|
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Types
|
5
|
+
module Relay
|
6
|
+
module ConnectionBehaviors
|
7
|
+
extend Forwardable
|
8
|
+
def_delegators :@object, :cursor_from_node, :parent
|
9
|
+
|
10
|
+
def self.included(child_class)
|
11
|
+
child_class.extend(ClassMethods)
|
12
|
+
child_class.extend(Relay::DefaultRelay)
|
13
|
+
child_class.default_relay(true)
|
14
|
+
child_class.node_nullable(true)
|
15
|
+
add_page_info_field(child_class)
|
16
|
+
end
|
17
|
+
|
18
|
+
module ClassMethods
|
19
|
+
# @return [Class]
|
20
|
+
attr_reader :node_type
|
21
|
+
|
22
|
+
# @return [Class]
|
23
|
+
attr_reader :edge_class
|
24
|
+
|
25
|
+
# Configure this connection to return `edges` and `nodes` based on `edge_type_class`.
|
26
|
+
#
|
27
|
+
# This method will use the inputs to create:
|
28
|
+
# - `edges` field
|
29
|
+
# - `nodes` field
|
30
|
+
# - description
|
31
|
+
#
|
32
|
+
# It's called when you subclass this base connection, trying to use the
|
33
|
+
# class name to set defaults. You can call it again in the class definition
|
34
|
+
# to override the default (or provide a value, if the default lookup failed).
|
35
|
+
def edge_type(edge_type_class, edge_class: GraphQL::Relay::Edge, node_type: edge_type_class.node_type, nodes_field: true, node_nullable: self.node_nullable)
|
36
|
+
# Set this connection's graphql name
|
37
|
+
node_type_name = node_type.graphql_name
|
38
|
+
|
39
|
+
@node_type = node_type
|
40
|
+
@edge_type = edge_type_class
|
41
|
+
@edge_class = edge_class
|
42
|
+
|
43
|
+
field :edges, [edge_type_class, null: true],
|
44
|
+
null: true,
|
45
|
+
description: "A list of edges.",
|
46
|
+
legacy_edge_class: edge_class, # This is used by the old runtime only, for EdgesInstrumentation
|
47
|
+
connection: false
|
48
|
+
|
49
|
+
define_nodes_field(node_nullable) if nodes_field
|
50
|
+
|
51
|
+
description("The connection type for #{node_type_name}.")
|
52
|
+
end
|
53
|
+
|
54
|
+
# Filter this list according to the way its node type would scope them
|
55
|
+
def scope_items(items, context)
|
56
|
+
node_type.scope_items(items, context)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Add the shortcut `nodes` field to this connection and its subclasses
|
60
|
+
def nodes_field(node_nullable: self.node_nullable)
|
61
|
+
define_nodes_field(node_nullable)
|
62
|
+
end
|
63
|
+
|
64
|
+
def authorized?(obj, ctx)
|
65
|
+
true # Let nodes be filtered out
|
66
|
+
end
|
67
|
+
|
68
|
+
def accessible?(ctx)
|
69
|
+
node_type.accessible?(ctx)
|
70
|
+
end
|
71
|
+
|
72
|
+
def visible?(ctx)
|
73
|
+
node_type.visible?(ctx)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Set the default `node_nullable` for this class and its child classes. (Defaults to `true`.)
|
77
|
+
# Use `node_nullable(false)` in your base class to make non-null `node` and `nodes` fields.
|
78
|
+
def node_nullable(new_value = nil)
|
79
|
+
if new_value.nil?
|
80
|
+
@node_nullable || superclass.node_nullable
|
81
|
+
else
|
82
|
+
@node_nullable ||= new_value
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
def define_nodes_field(nullable)
|
89
|
+
field :nodes, [@node_type, null: nullable],
|
90
|
+
null: nullable,
|
91
|
+
description: "A list of nodes.",
|
92
|
+
connection: false
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
class << self
|
97
|
+
def add_page_info_field(obj_type)
|
98
|
+
obj_type.field :page_info, GraphQL::Types::Relay::PageInfo, null: false, description: "Information to aid in pagination."
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# By default this calls through to the ConnectionWrapper's edge nodes method,
|
103
|
+
# but sometimes you need to override it to support the `nodes` field
|
104
|
+
def nodes
|
105
|
+
@object.edge_nodes
|
106
|
+
end
|
107
|
+
|
108
|
+
def edges
|
109
|
+
if @object.is_a?(GraphQL::Pagination::Connection)
|
110
|
+
@object.edges
|
111
|
+
elsif context.interpreter?
|
112
|
+
context.schema.after_lazy(object.edge_nodes) do |nodes|
|
113
|
+
nodes.map { |n| self.class.edge_class.new(n, object) }
|
114
|
+
end
|
115
|
+
else
|
116
|
+
# This is done by edges_instrumentation
|
117
|
+
@object.edge_nodes
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Types
|
5
|
+
module Relay
|
6
|
+
module DefaultRelay
|
7
|
+
def self.extended(child_class)
|
8
|
+
child_class.default_relay(true)
|
9
|
+
end
|
10
|
+
|
11
|
+
def default_relay(new_value)
|
12
|
+
@default_relay = new_value
|
13
|
+
end
|
14
|
+
|
15
|
+
def default_relay?
|
16
|
+
!!@default_relay
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_graphql
|
20
|
+
type_defn = super
|
21
|
+
type_defn.default_relay = default_relay?
|
22
|
+
type_defn
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Types
|
5
|
+
module Relay
|
6
|
+
module EdgeBehaviors
|
7
|
+
def self.included(child_class)
|
8
|
+
child_class.description("An edge in a connection.")
|
9
|
+
child_class.field(:cursor, String, null: false, description: "A cursor for use in pagination.")
|
10
|
+
child_class.extend(ClassMethods)
|
11
|
+
end
|
12
|
+
|
13
|
+
module ClassMethods
|
14
|
+
# Get or set the Object type that this edge wraps.
|
15
|
+
#
|
16
|
+
# @param node_type [Class] A `Schema::Object` subclass
|
17
|
+
# @param null [Boolean]
|
18
|
+
def node_type(node_type = nil, null: true)
|
19
|
+
if node_type
|
20
|
+
@node_type = node_type
|
21
|
+
# Add a default `node` field
|
22
|
+
field :node, node_type, null: null, description: "The item at the end of the edge.", connection: false
|
23
|
+
end
|
24
|
+
@node_type
|
25
|
+
end
|
26
|
+
|
27
|
+
def authorized?(obj, ctx)
|
28
|
+
true
|
29
|
+
end
|
30
|
+
|
31
|
+
def accessible?(ctx)
|
32
|
+
node_type.accessible?(ctx)
|
33
|
+
end
|
34
|
+
|
35
|
+
def visible?(ctx)
|
36
|
+
node_type.visible?(ctx)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Types
|
5
|
+
module Relay
|
6
|
+
module HasNodeField
|
7
|
+
def self.included(child_class)
|
8
|
+
child_class.field(**field_options, &field_block)
|
9
|
+
end
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def field_options
|
13
|
+
{
|
14
|
+
name: "node",
|
15
|
+
owner: nil,
|
16
|
+
type: GraphQL::Types::Relay::Node,
|
17
|
+
null: true,
|
18
|
+
description: "Fetches an object given its ID.",
|
19
|
+
relay_node_field: true,
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
def field_block
|
24
|
+
Proc.new {
|
25
|
+
argument :id, "ID!", required: true,
|
26
|
+
description: "ID of the object."
|
27
|
+
|
28
|
+
def resolve(obj, args, ctx)
|
29
|
+
ctx.schema.object_from_id(args[:id], ctx)
|
30
|
+
end
|
31
|
+
|
32
|
+
def resolve_field(obj, args, ctx)
|
33
|
+
resolve(obj, args, ctx)
|
34
|
+
end
|
35
|
+
}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Types
|
5
|
+
module Relay
|
6
|
+
module HasNodesField
|
7
|
+
def self.included(child_class)
|
8
|
+
child_class.field(**field_options, &field_block)
|
9
|
+
end
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def field_options
|
13
|
+
{
|
14
|
+
name: "nodes",
|
15
|
+
owner: nil,
|
16
|
+
type: [GraphQL::Types::Relay::Node, null: true],
|
17
|
+
null: false,
|
18
|
+
description: "Fetches a list of objects given a list of IDs.",
|
19
|
+
relay_nodes_field: true,
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
def field_block
|
24
|
+
Proc.new {
|
25
|
+
argument :ids, "[ID!]!", required: true,
|
26
|
+
description: "IDs of the objects."
|
27
|
+
|
28
|
+
def resolve(obj, args, ctx)
|
29
|
+
args[:ids].map { |id| ctx.schema.object_from_id(id, ctx) }
|
30
|
+
end
|
31
|
+
|
32
|
+
def resolve_field(obj, args, ctx)
|
33
|
+
resolve(obj, args, ctx)
|
34
|
+
end
|
35
|
+
}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -7,10 +7,8 @@ module GraphQL
|
|
7
7
|
# or you can take it as inspiration for your own implementation
|
8
8
|
# of the `Node` interface.
|
9
9
|
module Node
|
10
|
-
include
|
11
|
-
|
12
|
-
description "An object with an ID."
|
13
|
-
field(:id, ID, null: false, description: "ID of the object.")
|
10
|
+
include GraphQL::Schema::Interface
|
11
|
+
include Types::Relay::NodeBehaviors
|
14
12
|
end
|
15
13
|
end
|
16
14
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Types
|
5
|
+
module Relay
|
6
|
+
module NodeBehaviors
|
7
|
+
def self.included(child_module)
|
8
|
+
child_module.extend(DefaultRelay)
|
9
|
+
child_module.description("An object with an ID.")
|
10
|
+
child_module.field(:id, ID, null: false, description: "ID of the object.")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|