-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
interface.rb
103 lines (91 loc) · 4.02 KB
/
interface.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# frozen_string_literal: true
module GraphQL
class Schema
module Interface
include GraphQL::Schema::Member::GraphQLTypeNames
module DefinitionMethods
include GraphQL::Schema::Member::BaseDSLMethods
# ConfigurationExtension's responsibilities are in `def included` below
include GraphQL::Schema::Member::TypeSystemHelpers
include GraphQL::Schema::Member::HasFields
include GraphQL::Schema::Member::HasPath
include GraphQL::Schema::Member::RelayShortcuts
include GraphQL::Schema::Member::Scoped
include GraphQL::Schema::Member::HasAstNode
include GraphQL::Schema::Member::HasUnresolvedTypeError
include GraphQL::Schema::Member::HasDirectives
include GraphQL::Schema::Member::HasInterfaces
# Methods defined in this block will be:
# - Added as class methods to this interface
# - Added as class methods to all child interfaces
def definition_methods(&block)
self::DefinitionMethods.module_eval(&block)
end
# @see {Schema::Warden} hides interfaces without visible implementations
def visible?(context)
true
end
def type_membership_class(membership_class = nil)
if membership_class
@type_membership_class = membership_class
else
@type_membership_class || find_inherited_value(:type_membership_class, GraphQL::Schema::TypeMembership)
end
end
# Here's the tricky part. Make sure behavior keeps making its way down the inheritance chain.
def included(child_class)
if !child_class.is_a?(Class)
# In this case, it's been included into another interface.
# This is how interface inheritance is implemented
# We need this before we can call `own_interfaces`
child_class.extend(Schema::Interface::DefinitionMethods)
child_class.type_membership_class(self.type_membership_class)
child_class.ancestors.reverse_each do |ancestor|
if ancestor.const_defined?(:DefinitionMethods)
child_class.extend(ancestor::DefinitionMethods)
end
end
# Use an instance variable to tell whether it's been included previously or not;
# You can't use constant detection because constants are brought into scope
# by `include`, which has already happened at this point.
if !child_class.instance_variable_defined?(:@_definition_methods)
defn_methods_module = Module.new
child_class.instance_variable_set(:@_definition_methods, defn_methods_module)
child_class.const_set(:DefinitionMethods, defn_methods_module)
child_class.extend(child_class::DefinitionMethods)
end
child_class.introspection(introspection)
child_class.description(description)
# If interfaces are mixed into each other, only define this class once
if !child_class.const_defined?(:UnresolvedTypeError, false)
add_unresolved_type_error(child_class)
end
elsif child_class < GraphQL::Schema::Object
# This is being included into an object type, make sure it's using `implements(...)`
backtrace_line = caller(0, 10).find { |line| line.include?("schema/member/has_interfaces.rb") && line.include?("in `implements'")}
if !backtrace_line
raise "Attach interfaces using `implements(#{self})`, not `include(#{self})`"
end
end
super
end
def orphan_types(*types)
if types.any?
@orphan_types = types
else
all_orphan_types = @orphan_types || []
all_orphan_types += super if defined?(super)
all_orphan_types.uniq
end
end
def kind
GraphQL::TypeKinds::INTERFACE
end
end
extend DefinitionMethods
def unwrap
self
end
end
end
end