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.
Files changed (124) hide show
  1. checksums.yaml +5 -5
  2. data/lib/generators/graphql/install_generator.rb +14 -8
  3. data/lib/graphql.rb +1 -24
  4. data/lib/graphql/backtrace.rb +1 -1
  5. data/lib/graphql/deprecated_dsl.rb +2 -2
  6. data/lib/graphql/execution/execute.rb +6 -0
  7. data/lib/graphql/execution/lazy/lazy_method_map.rb +1 -1
  8. data/lib/graphql/introspection/base_object.rb +1 -0
  9. data/lib/graphql/language/document_from_schema_definition.rb +4 -1
  10. data/lib/graphql/language/nodes.rb +5 -2
  11. data/lib/graphql/language/parser.rb +288 -288
  12. data/lib/graphql/language/parser.y +1 -1
  13. data/lib/graphql/language/printer.rb +12 -2
  14. data/lib/graphql/non_null_type.rb +1 -1
  15. data/lib/graphql/query.rb +1 -1
  16. data/lib/graphql/query/arguments.rb +1 -1
  17. data/lib/graphql/query/context.rb +2 -2
  18. data/lib/graphql/query/null_context.rb +1 -1
  19. data/lib/graphql/query/result.rb +1 -1
  20. data/lib/graphql/query/variables.rb +21 -3
  21. data/lib/graphql/relay.rb +1 -0
  22. data/lib/graphql/relay/mongo_relation_connection.rb +40 -0
  23. data/lib/graphql/scalar_type.rb +14 -2
  24. data/lib/graphql/schema.rb +17 -1
  25. data/lib/graphql/schema/argument.rb +39 -7
  26. data/lib/graphql/schema/enum.rb +7 -0
  27. data/lib/graphql/schema/field.rb +145 -39
  28. data/lib/graphql/schema/finder.rb +4 -4
  29. data/lib/graphql/schema/input_object.rb +13 -2
  30. data/lib/graphql/schema/interface.rb +50 -16
  31. data/lib/graphql/schema/list.rb +28 -0
  32. data/lib/graphql/schema/member.rb +8 -106
  33. data/lib/graphql/schema/member/accepts_definition.rb +58 -24
  34. data/lib/graphql/schema/member/base_dsl_methods.rb +96 -0
  35. data/lib/graphql/schema/member/build_type.rb +15 -9
  36. data/lib/graphql/schema/member/cached_graphql_definition.rb +26 -0
  37. data/lib/graphql/schema/member/graphql_type_names.rb +21 -0
  38. data/lib/graphql/schema/member/has_arguments.rb +1 -1
  39. data/lib/graphql/schema/member/has_fields.rb +91 -8
  40. data/lib/graphql/schema/member/type_system_helpers.rb +34 -0
  41. data/lib/graphql/schema/middleware_chain.rb +5 -1
  42. data/lib/graphql/schema/mutation.rb +24 -12
  43. data/lib/graphql/schema/non_null.rb +34 -0
  44. data/lib/graphql/schema/object.rb +24 -11
  45. data/lib/graphql/schema/relay_classic_mutation.rb +14 -11
  46. data/lib/graphql/schema/rescue_middleware.rb +8 -7
  47. data/lib/graphql/schema/scalar.rb +9 -2
  48. data/lib/graphql/schema/union.rb +4 -0
  49. data/lib/graphql/static_validation/definition_dependencies.rb +1 -1
  50. data/lib/graphql/static_validation/literal_validator.rb +16 -4
  51. data/lib/graphql/static_validation/validation_context.rb +1 -1
  52. data/lib/graphql/subscriptions.rb +90 -16
  53. data/lib/graphql/upgrader/member.rb +27 -89
  54. data/lib/graphql/version.rb +1 -1
  55. data/spec/dummy/app/channels/graphql_channel.rb +1 -1
  56. data/spec/dummy/log/test.log +206 -0
  57. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/-x/-xYZjAnuuzgR79fcznLTQtSdh6AARxu8FcQ_J6p7L3U.cache +0 -0
  58. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/13/13HiV12xyoQvT-1L39ZzLwMZxjyaGMiENmfw7f-QTIc.cache +0 -0
  59. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/3W/3Wtf5pCWdqq0AB-iB0Y9uUNrTkruRxIEf1XFn_BETU0.cache +1 -0
  60. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/5i/5iguGafb4hOn8262Kn8Q37ogNN9MxxQKGKNzHAzUcvI.cache +1 -0
  61. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/8m/8mj2T6yy847Mc2Z7k3Xzh8O91hhVJt3NrPe8ASNDlIA.cache +1 -0
  62. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/DT/DTQyMpr4ABZYQetsdRJ5A7S4jf1r3ie4FGOR7GZBNSs.cache +3 -0
  63. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Dq/DqJ5_yJPrP5iLlOQyTQsjAVI5FE5LCVDkED0f7GgsSo.cache +3 -0
  64. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F8/F8MUNRzORGFgr329fNM0xLaoWCXdv3BIalT7dsvLfjs.cache +0 -0
  65. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/KB/KB07ZaKNC5uXJ7TjLi-WqnY6g7dq8wWp_8N3HNjBNxg.cache +0 -0
  66. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Rw/RwDuCV-XpnCtjNkvhpJfBuxXMk0b5AD3L9eR6M-wcy0.cache +3 -0
  67. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/UL/ULdjhhb0bRuqmaG7XSZlFYzGYCXTDnqZuJBTWRlzqgw.cache +0 -0
  68. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Up/UpPNgh0yYoUsyMDh5zWqe_U6qJIyTC6-dxMMAs1vvlM.cache +1 -0
  69. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Wg/Wguh-szFGTI1gaL6npYwPekMXflugRei7F_mOyRucXg.cache +0 -0
  70. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/X-/X-khLYMA9mqFRPg3zAi86mREDxpKl4bdKYp3uF6WHos.cache +0 -0
  71. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/bi/BIkdhfxsezxM4q-HZ4oCNTq97WEJTigcq0tpX2cDvbY.cache +0 -0
  72. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ff/FfxmA4CMHQZT7exx0G7NS1Wpcnny0vzp-Jhc2H36bp8.cache +1 -0
  73. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/gE/gEiiG4GZNy_djEjK2pHm_NgA-gyhLZhdQvo0Yt96GqE.cache +0 -0
  74. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/gn/gnA9ZSqpjccNL2m8pe_jBvY6SinXlCzXDWyop83Od8s.cache +1 -0
  75. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/lO/lOAan3cMwCE_Hli6gsDML88xFNfn0nxPmvrSkW7eEOw.cache +1 -0
  76. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/m1/M1pv8MJEPLXGLvS8QxVh3DSO9cI4mRt5FHFWdrvUj6o.cache +2 -0
  77. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/m7/m77qH7ZqH0_0SmwJbiKGDd-aLau1Dav847DC6ge46zY.cache +1 -0
  78. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/sj/sjRjnjRB37lH2vrgtkdJ8Cz84__IJ978IuKTM7HcztI.cache +0 -0
  79. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/um/um1JrirR4hJhK-1rE-HywlyCi5ibgxHVrReiujZBWJM.cache +1 -0
  80. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/v4/v4fwVytD7ITcE0_GDbslZEYud8a5Okm85fV1o7SDl6g.cache +0 -0
  81. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/v_/v_0PAQt0iipQjFP5zjgkkk9Stnpf4VzvnMv67d1Keuw.cache +1 -0
  82. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/wd/wdT9U4MKxe1PyqNjVuCKMpCl3dxGCIRJIlwUTfh2DQU.cache +1 -0
  83. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/xI/xIaxut_fEIhKBDqljTNwYaADK9kj3gG0ESrfHs-5_og.cache +3 -0
  84. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/y0/y0SJOqIx2fn1SKqOkAihsQow0trRJrSIyAswufVuoA8.cache +0 -0
  85. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/zg/zgpzeaX-KZErHyGJ1aBH3ZusweNXMneVZule88XsIJI.cache +1 -0
  86. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/zy/zYFltDy-8VC-uKq2BVEiJJyYXNFvVzAKuMlR3ZIYZsk.cache +0 -0
  87. data/spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png +0 -0
  88. data/spec/fixtures/upgrader/photo.original.rb +10 -0
  89. data/spec/fixtures/upgrader/photo.transformed.rb +12 -0
  90. data/spec/fixtures/upgrader/starrable.original.rb +4 -1
  91. data/spec/fixtures/upgrader/starrable.transformed.rb +25 -22
  92. data/spec/fixtures/upgrader/subscribable.transformed.rb +32 -33
  93. data/spec/graphql/execution_error_spec.rb +18 -0
  94. data/spec/graphql/introspection/schema_type_spec.rb +1 -0
  95. data/spec/graphql/object_type_spec.rb +2 -1
  96. data/spec/graphql/query/variables_spec.rb +41 -0
  97. data/spec/graphql/relay/mongo_relation_connection_spec.rb +474 -0
  98. data/spec/graphql/schema/argument_spec.rb +65 -9
  99. data/spec/graphql/schema/build_from_definition_spec.rb +4 -2
  100. data/spec/graphql/schema/enum_spec.rb +1 -1
  101. data/spec/graphql/schema/field_spec.rb +79 -4
  102. data/spec/graphql/schema/input_object_spec.rb +56 -0
  103. data/spec/graphql/schema/instrumentation_spec.rb +4 -3
  104. data/spec/graphql/schema/interface_spec.rb +40 -25
  105. data/spec/graphql/schema/member/accepts_definition_spec.rb +38 -11
  106. data/spec/graphql/schema/member/has_fields_spec.rb +129 -0
  107. data/spec/graphql/schema/member/type_system_helpers_spec.rb +63 -0
  108. data/spec/graphql/schema/mutation_spec.rb +48 -0
  109. data/spec/graphql/schema/object_spec.rb +34 -8
  110. data/spec/graphql/schema/relay_classic_mutation_spec.rb +10 -0
  111. data/spec/graphql/schema/rescue_middleware_spec.rb +11 -0
  112. data/spec/graphql/schema/scalar_spec.rb +55 -0
  113. data/spec/graphql/subscriptions_spec.rb +31 -4
  114. data/spec/graphql/upgrader/member_spec.rb +14 -6
  115. data/spec/spec_helper.rb +7 -0
  116. data/spec/support/dummy/schema.rb +8 -0
  117. data/spec/support/jazz.rb +89 -19
  118. data/spec/support/star_trek/data.rb +109 -0
  119. data/spec/support/star_trek/schema.rb +388 -0
  120. metadata +80 -7
  121. data/lib/graphql/schema/field/dynamic_resolve.rb +0 -70
  122. data/lib/graphql/schema/field/unwrapped_resolve.rb +0 -20
  123. data/lib/graphql/schema/member/list_type_proxy.rb +0 -25
  124. data/lib/graphql/schema/member/non_null_type_proxy.rb +0 -25
@@ -5,16 +5,16 @@ module GraphQL
5
5
  # Find schema members using string paths
6
6
  #
7
7
  # @example Finding object types
8
- # MySchema.find("SomeObjectType")
8
+ # MySchema.find("SomeObjectType")
9
9
  #
10
10
  # @example Finding fields
11
- # MySchema.find("SomeObjectType.myField")
11
+ # MySchema.find("SomeObjectType.myField")
12
12
  #
13
13
  # @example Finding arguments
14
- # MySchema.find("SomeObjectType.myField.anArgument")
14
+ # MySchema.find("SomeObjectType.myField.anArgument")
15
15
  #
16
16
  # @example Finding directives
17
- # MySchema.find("@include")
17
+ # MySchema.find("@include")
18
18
  #
19
19
  class Finder
20
20
  class MemberNotFoundError < ArgumentError; end
@@ -3,14 +3,21 @@ module GraphQL
3
3
  class Schema
4
4
  class InputObject < GraphQL::Schema::Member
5
5
  extend GraphQL::Schema::Member::AcceptsDefinition
6
- extend GraphQL::Delegate
6
+ extend Forwardable
7
7
  extend GraphQL::Schema::Member::HasArguments
8
8
 
9
9
  def initialize(values, context:, defaults_used:)
10
+ @context = context
10
11
  @arguments = self.class.arguments_class.new(values, context: context, defaults_used: defaults_used)
11
12
  # Symbolized, underscored hash:
12
13
  @ruby_style_hash = @arguments.to_kwargs
13
- @context = context
14
+ # Apply prepares, not great to have it duplicated here.
15
+ self.class.arguments.each do |name, arg_defn|
16
+ ruby_kwargs_key = arg_defn.keyword
17
+ if @ruby_style_hash.key?(ruby_kwargs_key) && arg_defn.prepare
18
+ @ruby_style_hash[ruby_kwargs_key] = arg_defn.prepare_value(self, @ruby_style_hash[ruby_kwargs_key])
19
+ end
20
+ end
14
21
  end
15
22
 
16
23
  # @return [GraphQL::Query::Context] The context for this query
@@ -70,6 +77,10 @@ module GraphQL
70
77
  type_defn.arguments_class = self
71
78
  type_defn
72
79
  end
80
+
81
+ def kind
82
+ GraphQL::TypeKinds::INPUT_OBJECT
83
+ end
73
84
  end
74
85
  end
75
86
  end
@@ -1,25 +1,44 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
3
  class Schema
4
- class Interface < GraphQL::Schema::Member
5
- extend GraphQL::Schema::Member::HasFields
6
- extend GraphQL::Schema::Member::AcceptsDefinition
4
+ module Interface
5
+ include GraphQL::Schema::Member::GraphQLTypeNames
6
+ module DefinitionMethods
7
+ include GraphQL::Schema::Member::CachedGraphQLDefinition
8
+ include GraphQL::Relay::TypeExtensions
9
+ include GraphQL::Schema::Member::BaseDSLMethods
10
+ include GraphQL::Schema::Member::TypeSystemHelpers
11
+ include GraphQL::Schema::Member::HasFields
7
12
 
8
- class << self
9
- # Always set up a `self::Implementation` module,
10
- # which may or may not be added to.
11
- def inherited(child_cls)
12
- # This module will be mixed in to each object class,
13
- # so it can contain methods to implement fields.
14
- # It's always added to interfaces, but sometimes it's left empty.
15
- child_cls.const_set(:Implementation, Module.new)
13
+ # Methods defined in this block will be:
14
+ # - Added as class methods to this interface
15
+ # - Added as class methods to all child interfaces
16
+ def definition_methods(&block)
17
+ self::DefinitionMethods.module_eval(&block)
16
18
  end
17
19
 
18
- # When this interface is added to a `GraphQL::Schema::Object`,
19
- # it calls this method. We add methods to the object by convention,
20
- # a nested module named `Implementation`
21
- def implemented(object_class)
22
- object_class.include(self::Implementation)
20
+ # Here's the tricky part. Make sure behavior keeps making its way down the inheritance chain.
21
+ def included(child_class)
22
+ if !child_class.is_a?(Class)
23
+ # In this case, it's been included into another interface.
24
+ # This is how interface inheritance is implemented
25
+ child_class.const_set(:DefinitionMethods, Module.new)
26
+ child_class.extend(child_class::DefinitionMethods)
27
+ # We need this before we can call `own_interfaces`
28
+ child_class.extend(Schema::Interface::DefinitionMethods)
29
+ child_class.own_interfaces << self
30
+ child_class.own_interfaces.each do |interface_defn|
31
+ child_class.extend(interface_defn::DefinitionMethods)
32
+ end
33
+ elsif child_class < GraphQL::Schema::Object
34
+ # This is being included into an object type, make sure it's using `implements(...)`
35
+ backtrace_line = caller(0, 10).find { |line| line.include?("schema/object.rb") && line.include?("in `implements'")}
36
+ if !backtrace_line
37
+ raise "Attach interfaces using `implements(#{self})`, not `include(#{self})`"
38
+ end
39
+ end
40
+
41
+ super
23
42
  end
24
43
 
25
44
  def orphan_types(*types)
@@ -47,7 +66,22 @@ module GraphQL
47
66
  end
48
67
  type_defn
49
68
  end
69
+
70
+ def kind
71
+ GraphQL::TypeKinds::INTERFACE
72
+ end
73
+
74
+ protected
75
+
76
+ def own_interfaces
77
+ @own_interfaces ||= []
78
+ end
50
79
  end
80
+
81
+ # Extend this _after_ `DefinitionMethods` is defined, so it will be used
82
+ extend GraphQL::Schema::Member::AcceptsDefinition
83
+
84
+ extend DefinitionMethods
51
85
  end
52
86
  end
53
87
  end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ class Schema
5
+ # Represents a list type in the schema.
6
+ # Wraps a {Schema::Member} as a list type.
7
+ # @see {Schema::Member::TypeSystemHelpers#to_list_type}
8
+ class List
9
+ include GraphQL::Schema::Member::CachedGraphQLDefinition
10
+ include GraphQL::Schema::Member::TypeSystemHelpers
11
+
12
+ # @return [Class, Module] The inner type of this list, the type of which one or more objects may be present.
13
+ attr_reader :of_type
14
+
15
+ def initialize(of_type)
16
+ @of_type = of_type
17
+ end
18
+
19
+ def to_graphql
20
+ @of_type.graphql_definition.to_list_type
21
+ end
22
+
23
+ def kind
24
+ GraphQL::TypeKinds::LIST
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,5 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
  require 'graphql/schema/member/accepts_definition'
3
+ require 'graphql/schema/member/base_dsl_methods'
4
+ require 'graphql/schema/member/cached_graphql_definition'
5
+ require 'graphql/schema/member/graphql_type_names'
6
+ require 'graphql/schema/member/type_system_helpers'
3
7
  require "graphql/relay/type_extensions"
4
8
 
5
9
  module GraphQL
@@ -9,117 +13,15 @@ module GraphQL
9
13
  # @api private
10
14
  class Schema
11
15
  class Member
12
- # Adds a layer of caching over user-supplied `.to_graphql` methods.
13
- # Users override `.to_graphql`, but all runtime code should use `.graphql_definition`.
14
- module CachedGraphQLDefinition
15
- # A cached result of {.to_graphql}.
16
- # It's cached here so that user-overridden {.to_graphql} implementations
17
- # are also cached
18
- def graphql_definition
19
- @graphql_definition ||= to_graphql
20
- end
21
-
22
- def initialize_copy(original)
23
- super
24
- @graphql_definition = nil
25
- end
26
- end
27
-
28
- # These constants are interpreted as GraphQL types
29
- #
30
- # @example
31
- # field :is_draft, Boolean, null: false
32
- # field :id, ID, null: false
33
- # field :score, Int, null: false
34
- module GraphQLTypeNames
35
- Boolean = "Boolean"
36
- ID = "ID"
37
- Int = "Int"
38
- end
39
-
40
16
  include GraphQLTypeNames
41
- class << self
42
- include CachedGraphQLDefinition
43
- include GraphQL::Relay::TypeExtensions
44
- # Call this with a new name to override the default name for this schema member; OR
45
- # call it without an argument to get the name of this schema member
46
- #
47
- # The default name is the Ruby constant name,
48
- # without any namespaces and with any `-Type` suffix removed
49
- # @param new_name [String]
50
- # @return [String]
51
- def graphql_name(new_name = nil)
52
- if new_name
53
- @graphql_name = new_name
54
- else
55
- overridden_graphql_name || self.name.split("::").last.sub(/Type\Z/, "")
56
- end
57
- end
58
-
59
- # Just a convenience method to point out that people should use graphql_name instead
60
- def name(new_name = nil)
61
- return super() if new_name.nil?
62
-
63
- fail(
64
- "The new name override method is `graphql_name`, not `name`. Usage: "\
65
- "graphql_name \"#{new_name}\""
66
- )
67
- end
68
-
69
- # Call this method to provide a new description; OR
70
- # call it without an argument to get the description
71
- # @param new_description [String]
72
- # @return [String]
73
- def description(new_description = nil)
74
- if new_description
75
- @description = new_description
76
- else
77
- @description || (superclass <= GraphQL::Schema::Member ? superclass.description : nil)
78
- end
79
- end
80
-
81
- # @return [Boolean] If true, this object is part of the introspection system
82
- def introspection(new_introspection = nil)
83
- if !new_introspection.nil?
84
- @introspection = new_introspection
85
- else
86
- @introspection || (superclass <= Schema::Member ? superclass.introspection : false)
87
- end
88
- end
89
-
90
- # The mutation this type was derived from, if it was derived from a mutation
91
- # @return [Class]
92
- def mutation(mutation_class = nil)
93
- if mutation_class
94
- @mutation = mutation_class
95
- end
96
- @mutation
97
- end
98
-
99
- def to_graphql
100
- raise NotImplementedError
101
- end
102
-
103
- def to_list_type
104
- ListTypeProxy.new(self)
105
- end
106
-
107
- def to_non_null_type
108
- NonNullTypeProxy.new(self)
109
- end
110
-
111
- protected
112
-
113
- def overridden_graphql_name
114
- @graphql_name || (superclass <= GraphQL::Schema::Member ? superclass.overridden_graphql_name : nil)
115
- end
116
- end
17
+ extend CachedGraphQLDefinition
18
+ extend GraphQL::Relay::TypeExtensions
19
+ extend BaseDSLMethods
20
+ extend TypeSystemHelpers
117
21
  end
118
22
  end
119
23
  end
120
24
 
121
- require 'graphql/schema/member/list_type_proxy'
122
- require 'graphql/schema/member/non_null_type_proxy'
123
25
  require 'graphql/schema/member/has_arguments'
124
26
  require 'graphql/schema/member/has_fields'
125
27
  require 'graphql/schema/member/instrumentation'
@@ -37,47 +37,81 @@ module GraphQL
37
37
  # Account.graphql_definition.metadata[:permission_level] # => 1
38
38
  module AcceptsDefinition
39
39
  def self.included(child)
40
- child.extend(ClassMethods)
40
+ child.extend(AcceptsDefinitionDefinitionMethods)
41
41
  child.prepend(ToGraphQLExtension)
42
42
  child.prepend(InitializeExtension)
43
43
  end
44
44
 
45
45
  def self.extended(child)
46
- child.extend(ClassMethods)
47
- # I tried to use `super`, but super isn't quite right
48
- # since the method is defined in the same class itself,
49
- # not the superclass
50
- child.class_eval do
51
- class << self
52
- prepend(ToGraphQLExtension)
46
+ if defined?(child::DefinitionMethods)
47
+ child::DefinitionMethods.include(AcceptsDefinitionDefinitionMethods)
48
+ child::DefinitionMethods.prepend(ToGraphQLExtension)
49
+ else
50
+ child.extend(AcceptsDefinitionDefinitionMethods)
51
+ # I tried to use `super`, but super isn't quite right
52
+ # since the method is defined in the same class itself,
53
+ # not the superclass
54
+ child.class_eval do
55
+ class << self
56
+ prepend(ToGraphQLExtension)
57
+ end
53
58
  end
54
59
  end
55
60
  end
56
61
 
57
- module ClassMethods
62
+ module AcceptsDefinitionDefinitionMethods
58
63
  def accepts_definition(name)
59
- @accepts_definition_methods ||= []
60
- @accepts_definition_methods << name
64
+ own_accepts_definition_methods << name
65
+
61
66
  ivar_name = "@#{name}_args"
62
- define_singleton_method(name) do |*args|
63
- if args.any?
64
- instance_variable_set(ivar_name, args)
67
+ if self.is_a?(Class)
68
+ define_singleton_method(name) do |*args|
69
+ if args.any?
70
+ instance_variable_set(ivar_name, args)
71
+ end
72
+ instance_variable_get(ivar_name)
65
73
  end
66
- instance_variable_get(ivar_name)
67
- end
68
74
 
69
- define_method(name) do |*args|
70
- if args.any?
71
- instance_variable_set(ivar_name, args)
75
+ define_method(name) do |*args|
76
+ if args.any?
77
+ instance_variable_set(ivar_name, args)
78
+ end
79
+ instance_variable_get(ivar_name)
80
+ end
81
+ else
82
+ # Special handling for interfaces, define it here
83
+ # so it's appropriately passed down
84
+ self::DefinitionMethods.module_eval do
85
+ define_method(name) do |*args|
86
+ if args.any?
87
+ instance_variable_set(ivar_name, args)
88
+ end
89
+ instance_variable_get(ivar_name)
90
+ end
72
91
  end
73
- instance_variable_get(ivar_name)
74
92
  end
75
93
  end
76
94
 
77
95
  def accepts_definition_methods
78
- @accepts_definition_methods ||= []
79
- sc = self.is_a?(Class) ? superclass : self.class.superclass
80
- @accepts_definition_methods + (sc.respond_to?(:accepts_definition_methods) ? sc.accepts_definition_methods : [])
96
+ inherited_methods = if self.is_a?(Class)
97
+ superclass.respond_to?(:accepts_definition_methods) ? superclass.accepts_definition_methods : []
98
+ elsif self.is_a?(Module)
99
+ m = []
100
+ ancestors.each do |a|
101
+ if a.respond_to?(:own_accepts_definition_methods)
102
+ m.concat(a.own_accepts_definition_methods)
103
+ end
104
+ end
105
+ m
106
+ else
107
+ self.class.accepts_definition_methods
108
+ end
109
+
110
+ own_accepts_definition_methods + inherited_methods
111
+ end
112
+
113
+ def own_accepts_definition_methods
114
+ @own_accepts_definition_methods ||= []
81
115
  end
82
116
  end
83
117
 
@@ -85,7 +119,7 @@ module GraphQL
85
119
  def to_graphql
86
120
  defn = super
87
121
  accepts_definition_methods.each do |method_name|
88
- value = instance_variable_get("@#{method_name}_args")
122
+ value = public_send(method_name)
89
123
  if !value.nil?
90
124
  defn = defn.redefine { public_send(method_name, *value) }
91
125
  end
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ class Schema
5
+ class Member
6
+ # DSL methods shared by lots of things in the GraphQL Schema.
7
+ # @api private
8
+ # @see Classes that extend this, eg {GraphQL::Schema::Object}
9
+ module BaseDSLMethods
10
+ # Call this with a new name to override the default name for this schema member; OR
11
+ # call it without an argument to get the name of this schema member
12
+ #
13
+ # The default name is the Ruby constant name,
14
+ # without any namespaces and with any `-Type` suffix removed
15
+ # @param new_name [String]
16
+ # @return [String]
17
+ def graphql_name(new_name = nil)
18
+ case
19
+ when new_name
20
+ @graphql_name = new_name
21
+ when overridden = overridden_graphql_name
22
+ overridden
23
+ else # Fallback to Ruby constant name
24
+ raise NotImplementedError, 'Anonymous class should declare an `graphql_name`' if name.nil?
25
+
26
+ name.split("::").last.sub(/Type\Z/, "")
27
+ end
28
+ end
29
+
30
+ # Just a convenience method to point out that people should use graphql_name instead
31
+ def name(new_name = nil)
32
+ return super() if new_name.nil?
33
+
34
+ fail(
35
+ "The new name override method is `graphql_name`, not `name`. Usage: "\
36
+ "graphql_name \"#{new_name}\""
37
+ )
38
+ end
39
+
40
+ # Call this method to provide a new description; OR
41
+ # call it without an argument to get the description
42
+ # @param new_description [String]
43
+ # @return [String]
44
+ def description(new_description = nil)
45
+ if new_description
46
+ @description = new_description
47
+ else
48
+ @description || find_inherited_method(:description, nil)
49
+ end
50
+ end
51
+
52
+ # @return [Boolean] If true, this object is part of the introspection system
53
+ def introspection(new_introspection = nil)
54
+ if !new_introspection.nil?
55
+ @introspection = new_introspection
56
+ else
57
+ @introspection || find_inherited_method(:introspection, false)
58
+ end
59
+ end
60
+
61
+ # The mutation this type was derived from, if it was derived from a mutation
62
+ # @return [Class]
63
+ def mutation(mutation_class = nil)
64
+ if mutation_class
65
+ @mutation = mutation_class
66
+ end
67
+ @mutation
68
+ end
69
+
70
+ # @return [GraphQL::BaseType] Convert this type to a legacy-style object.
71
+ def to_graphql
72
+ raise NotImplementedError
73
+ end
74
+
75
+ def overridden_graphql_name
76
+ @graphql_name || find_inherited_method(:overridden_graphql_name, nil)
77
+ end
78
+
79
+ private
80
+
81
+ def find_inherited_method(method_name, default_value)
82
+ if self.is_a?(Class)
83
+ superclass.respond_to?(method_name) ? superclass.public_send(method_name) : default_value
84
+ else
85
+ ancestors[1..-1].each do |ancestor|
86
+ if ancestor.respond_to?(method_name)
87
+ return ancestor.public_send(method_name)
88
+ end
89
+ end
90
+ default_value
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end