graphql 1.7.14 → 1.8.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (149) hide show
  1. checksums.yaml +5 -5
  2. data/lib/generators/graphql/function_generator.rb +1 -1
  3. data/lib/generators/graphql/loader_generator.rb +1 -1
  4. data/lib/generators/graphql/mutation_generator.rb +1 -6
  5. data/lib/generators/graphql/templates/function.erb +2 -2
  6. data/lib/generators/graphql/templates/loader.erb +2 -2
  7. data/lib/graphql.rb +2 -0
  8. data/lib/graphql/argument.rb +0 -1
  9. data/lib/graphql/backwards_compatibility.rb +2 -3
  10. data/lib/graphql/base_type.rb +18 -16
  11. data/lib/graphql/compatibility/query_parser_specification.rb +0 -117
  12. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -14
  13. data/lib/graphql/define/assign_object_field.rb +5 -12
  14. data/lib/graphql/deprecated_dsl.rb +28 -0
  15. data/lib/graphql/directive.rb +0 -1
  16. data/lib/graphql/enum_type.rb +1 -3
  17. data/lib/graphql/execution.rb +0 -1
  18. data/lib/graphql/execution/multiplex.rb +29 -12
  19. data/lib/graphql/field.rb +5 -20
  20. data/lib/graphql/function.rb +12 -0
  21. data/lib/graphql/input_object_type.rb +1 -3
  22. data/lib/graphql/internal_representation/node.rb +14 -26
  23. data/lib/graphql/internal_representation/visit.rb +6 -3
  24. data/lib/graphql/introspection/arguments_field.rb +0 -1
  25. data/lib/graphql/introspection/enum_values_field.rb +0 -1
  26. data/lib/graphql/introspection/fields_field.rb +0 -1
  27. data/lib/graphql/introspection/input_fields_field.rb +0 -1
  28. data/lib/graphql/introspection/interfaces_field.rb +0 -1
  29. data/lib/graphql/introspection/of_type_field.rb +0 -1
  30. data/lib/graphql/introspection/possible_types_field.rb +0 -1
  31. data/lib/graphql/introspection/schema_field.rb +0 -1
  32. data/lib/graphql/introspection/type_by_name_field.rb +0 -1
  33. data/lib/graphql/introspection/typename_field.rb +0 -1
  34. data/lib/graphql/language.rb +0 -3
  35. data/lib/graphql/language/generation.rb +182 -3
  36. data/lib/graphql/language/lexer.rb +69 -144
  37. data/lib/graphql/language/lexer.rl +4 -15
  38. data/lib/graphql/language/nodes.rb +76 -136
  39. data/lib/graphql/language/parser.rb +621 -668
  40. data/lib/graphql/language/parser.y +11 -17
  41. data/lib/graphql/language/token.rb +3 -10
  42. data/lib/graphql/object_type.rb +6 -1
  43. data/lib/graphql/query.rb +13 -8
  44. data/lib/graphql/query/arguments.rb +33 -48
  45. data/lib/graphql/query/context.rb +1 -0
  46. data/lib/graphql/query/literal_input.rb +1 -4
  47. data/lib/graphql/relay/connection_resolve.rb +3 -0
  48. data/lib/graphql/relay/global_id_resolve.rb +5 -1
  49. data/lib/graphql/relay/relation_connection.rb +19 -14
  50. data/lib/graphql/schema.rb +219 -12
  51. data/lib/graphql/schema/argument.rb +33 -0
  52. data/lib/graphql/schema/build_from_definition.rb +18 -64
  53. data/lib/graphql/schema/enum.rb +76 -0
  54. data/lib/graphql/schema/field.rb +127 -0
  55. data/lib/graphql/schema/field/dynamic_resolve.rb +63 -0
  56. data/lib/graphql/schema/field/unwrapped_resolve.rb +20 -0
  57. data/lib/graphql/schema/input_object.rb +61 -0
  58. data/lib/graphql/schema/interface.rb +32 -0
  59. data/lib/graphql/schema/loader.rb +2 -2
  60. data/lib/graphql/schema/member.rb +97 -0
  61. data/lib/graphql/schema/member/build_type.rb +106 -0
  62. data/lib/graphql/schema/member/has_fields.rb +56 -0
  63. data/lib/graphql/schema/member/instrumentation.rb +113 -0
  64. data/lib/graphql/schema/member/list_type_proxy.rb +21 -0
  65. data/lib/graphql/schema/member/non_null_type_proxy.rb +21 -0
  66. data/lib/graphql/schema/object.rb +65 -0
  67. data/lib/graphql/schema/printer.rb +266 -33
  68. data/lib/graphql/schema/scalar.rb +25 -0
  69. data/lib/graphql/schema/traversal.rb +26 -17
  70. data/lib/graphql/schema/union.rb +48 -0
  71. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +1 -5
  72. data/lib/graphql/static_validation/rules/fields_will_merge.rb +8 -15
  73. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +1 -11
  74. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +5 -7
  75. data/lib/graphql/tracing.rb +0 -1
  76. data/lib/graphql/tracing/platform_tracing.rb +7 -20
  77. data/lib/graphql/tracing/scout_tracing.rb +2 -2
  78. data/lib/graphql/unresolved_type_error.rb +2 -3
  79. data/lib/graphql/version.rb +1 -1
  80. data/readme.md +1 -1
  81. data/spec/dummy/app/channels/graphql_channel.rb +1 -22
  82. data/spec/dummy/log/development.log +0 -239
  83. data/spec/dummy/log/test.log +0 -204
  84. data/spec/dummy/test/system/action_cable_subscription_test.rb +0 -4
  85. data/spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png +0 -0
  86. data/spec/generators/graphql/function_generator_spec.rb +0 -26
  87. data/spec/generators/graphql/loader_generator_spec.rb +0 -24
  88. data/spec/graphql/analysis/max_query_complexity_spec.rb +3 -3
  89. data/spec/graphql/analysis/max_query_depth_spec.rb +3 -3
  90. data/spec/graphql/backtrace_spec.rb +0 -10
  91. data/spec/graphql/base_type_spec.rb +5 -19
  92. data/spec/graphql/boolean_type_spec.rb +3 -3
  93. data/spec/graphql/directive_spec.rb +1 -3
  94. data/spec/graphql/enum_type_spec.rb +5 -18
  95. data/spec/graphql/execution/execute_spec.rb +1 -1
  96. data/spec/graphql/execution/multiplex_spec.rb +2 -2
  97. data/spec/graphql/float_type_spec.rb +2 -2
  98. data/spec/graphql/id_type_spec.rb +1 -1
  99. data/spec/graphql/input_object_type_spec.rb +2 -15
  100. data/spec/graphql/int_type_spec.rb +2 -2
  101. data/spec/graphql/internal_representation/rewrite_spec.rb +2 -2
  102. data/spec/graphql/introspection/schema_type_spec.rb +0 -1
  103. data/spec/graphql/language/generation_spec.rb +186 -21
  104. data/spec/graphql/language/lexer_spec.rb +1 -21
  105. data/spec/graphql/language/nodes_spec.rb +12 -21
  106. data/spec/graphql/language/parser_spec.rb +1 -1
  107. data/spec/graphql/query/arguments_spec.rb +15 -37
  108. data/spec/graphql/query/serial_execution/value_resolution_spec.rb +2 -2
  109. data/spec/graphql/query/variables_spec.rb +1 -1
  110. data/spec/graphql/query_spec.rb +5 -31
  111. data/spec/graphql/rake_task_spec.rb +1 -3
  112. data/spec/graphql/relay/base_connection_spec.rb +1 -1
  113. data/spec/graphql/relay/connection_instrumentation_spec.rb +2 -2
  114. data/spec/graphql/relay/connection_resolve_spec.rb +1 -1
  115. data/spec/graphql/relay/connection_type_spec.rb +1 -1
  116. data/spec/graphql/relay/mutation_spec.rb +3 -3
  117. data/spec/graphql/relay/relation_connection_spec.rb +1 -65
  118. data/spec/graphql/schema/build_from_definition_spec.rb +4 -86
  119. data/spec/graphql/schema/enum_spec.rb +60 -0
  120. data/spec/graphql/schema/field_spec.rb +14 -0
  121. data/spec/graphql/schema/input_object_spec.rb +43 -0
  122. data/spec/graphql/schema/interface_spec.rb +98 -0
  123. data/spec/graphql/schema/object_spec.rb +119 -0
  124. data/spec/graphql/schema/printer_spec.rb +15 -92
  125. data/spec/graphql/schema/scalar_spec.rb +40 -0
  126. data/spec/graphql/schema/union_spec.rb +35 -0
  127. data/spec/graphql/schema/validation_spec.rb +1 -1
  128. data/spec/graphql/schema/warden_spec.rb +11 -11
  129. data/spec/graphql/schema_spec.rb +25 -23
  130. data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +2 -10
  131. data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +2 -2
  132. data/spec/graphql/string_type_spec.rb +3 -3
  133. data/spec/graphql/subscriptions_spec.rb +1 -1
  134. data/spec/graphql/tracing/platform_tracing_spec.rb +1 -60
  135. data/spec/support/dummy/schema.rb +25 -39
  136. data/spec/support/jazz.rb +334 -0
  137. data/spec/support/lazy_helpers.rb +21 -23
  138. data/spec/support/star_wars/data.rb +7 -6
  139. data/spec/support/star_wars/schema.rb +109 -142
  140. metadata +39 -33
  141. data/lib/graphql/execution/instrumentation.rb +0 -82
  142. data/lib/graphql/language/block_string.rb +0 -47
  143. data/lib/graphql/language/document_from_schema_definition.rb +0 -277
  144. data/lib/graphql/language/printer.rb +0 -351
  145. data/lib/graphql/tracing/data_dog_tracing.rb +0 -49
  146. data/spec/graphql/execution/instrumentation_spec.rb +0 -165
  147. data/spec/graphql/language/block_string_spec.rb +0 -70
  148. data/spec/graphql/language/document_from_schema_definition_spec.rb +0 -770
  149. data/spec/graphql/language/printer_spec.rb +0 -203
@@ -82,7 +82,8 @@ rule
82
82
  | EQUALS literal_value { return val[1] }
83
83
 
84
84
  selection_set:
85
- LCURLY selection_list RCURLY { return val[1] }
85
+ LCURLY RCURLY { return [] }
86
+ | LCURLY selection_list RCURLY { return val[1] }
86
87
 
87
88
  selection_set_opt:
88
89
  /* none */ { return [] }
@@ -152,8 +153,12 @@ rule
152
153
  | operation_type
153
154
  | schema_keyword
154
155
 
156
+ name_list:
157
+ name { return [make_node(:TypeName, name: val[0])] }
158
+ | name_list name { val[0] << make_node(:TypeName, name: val[1]) }
159
+
155
160
  enum_value_definition:
156
- enum_name directives_list_opt { return make_node(:EnumValueDefinition, name: val[0], directives: val[1], description: get_description(val[0]), position_source: val[0]) }
161
+ enum_name directives_list_opt { return make_node(:EnumValueDefinition, name: val[0], directives: val[1], description: get_description(val[0])) }
157
162
 
158
163
  enum_value_definitions:
159
164
  enum_value_definition { return [val[0]] }
@@ -302,21 +307,11 @@ rule
302
307
 
303
308
  implements_opt:
304
309
  /* none */ { return [] }
305
- | IMPLEMENTS AMP interfaces_list { return val[2] }
306
- | IMPLEMENTS interfaces_list { return val[1] }
307
- | IMPLEMENTS legacy_interfaces_list { return val[1] }
308
-
309
- interfaces_list:
310
- name { return [make_node(:TypeName, name: val[0], position_source: val[0])] }
311
- | interfaces_list AMP name { val[0] << make_node(:TypeName, name: val[2], position_source: val[2]) }
312
-
313
- legacy_interfaces_list:
314
- name { return [make_node(:TypeName, name: val[0], position_source: val[0])] }
315
- | legacy_interfaces_list name { val[0] << make_node(:TypeName, name: val[1], position_source: val[1]) }
310
+ | IMPLEMENTS name_list { return val[1] }
316
311
 
317
312
  input_value_definition:
318
313
  name COLON type default_value_opt directives_list_opt {
319
- return make_node(:InputValueDefinition, name: val[0], type: val[2], default_value: val[3], directives: val[4], description: get_description(val[0]), position_source: val[0])
314
+ return make_node(:InputValueDefinition, name: val[0], type: val[2], default_value: val[3], directives: val[4], description: get_description(val[0]))
320
315
  }
321
316
 
322
317
  input_value_definition_list:
@@ -329,12 +324,11 @@ rule
329
324
 
330
325
  field_definition:
331
326
  name arguments_definitions_opt COLON type directives_list_opt {
332
- return make_node(:FieldDefinition, name: val[0], arguments: val[1], type: val[3], directives: val[4], description: get_description(val[0]), position_source: val[0])
327
+ return make_node(:FieldDefinition, name: val[0], arguments: val[1], type: val[3], directives: val[4], description: get_description(val[0]))
333
328
  }
334
329
 
335
330
  field_definition_list:
336
- /* none */ { return [] }
337
- | field_definition { return [val[0]] }
331
+ field_definition { return [val[0]] }
338
332
  | field_definition_list field_definition { val[0] << val[1] }
339
333
 
340
334
  interface_type_definition:
@@ -5,30 +5,23 @@ module GraphQL
5
5
  # Contains type, value and position data.
6
6
  class Token
7
7
  # @return [Symbol] The kind of token this is
8
- attr_reader :name
9
- # @return [String] The text of this token
10
- attr_reader :value
11
- attr_reader :prev_token, :line, :col
8
+ attr_reader :name, :prev_token, :line
12
9
 
13
10
  def initialize(value:, name:, line:, col:, prev_token:)
14
11
  @name = name
15
- @value = value.freeze
12
+ @value = value
16
13
  @line = line
17
14
  @col = col
18
15
  @prev_token = prev_token
19
16
  end
20
17
 
21
- alias to_s value
18
+ def to_s; @value; end
22
19
  def to_i; @value.to_i; end
23
20
  def to_f; @value.to_f; end
24
21
 
25
22
  def line_and_column
26
23
  [@line, @col]
27
24
  end
28
-
29
- def inspect
30
- "(#{@name} #{@value.inspect} [#{@line}:#{@col}])"
31
- end
32
25
  end
33
26
  end
34
27
  end
@@ -32,7 +32,7 @@ module GraphQL
32
32
  # @return [Hash<String => GraphQL::Field>] Map String fieldnames to their {GraphQL::Field} implementations
33
33
 
34
34
  # @!attribute mutation
35
- # @return [GraphQL::Relay::Mutation, nil] The mutation this object type was derived from, if it is an auto-generated payload type.
35
+ # @return [GraphQL::Relay::Mutation, nil] The mutation this field was derived from, if it was derived from a mutation
36
36
 
37
37
  def initialize
38
38
  super
@@ -102,6 +102,11 @@ module GraphQL
102
102
  dirty_ifaces.concat(interfaces)
103
103
  end
104
104
 
105
+ def name=(name)
106
+ GraphQL::NameValidator.validate!(name)
107
+ @name = name
108
+ end
109
+
105
110
  protected
106
111
 
107
112
  attr_reader :dirty_interfaces, :dirty_inherited_interfaces
data/lib/graphql/query.rb CHANGED
@@ -29,7 +29,10 @@ module GraphQL
29
29
  end
30
30
  end
31
31
 
32
- attr_reader :schema, :context, :root_value, :warden, :provided_variables
32
+ attr_reader :schema, :context, :warden, :provided_variables
33
+
34
+ # The value for root types
35
+ attr_accessor :root_value
33
36
 
34
37
  # @return [nil, String] The operation name provided by client or the one inferred from the document. Used to determine which operation to run.
35
38
  attr_accessor :operation_name
@@ -44,10 +47,6 @@ module GraphQL
44
47
  with_prepared_ast { @document }
45
48
  end
46
49
 
47
- def inspect
48
- "query ..."
49
- end
50
-
51
50
  # @return [String, nil] The name of the operation to run (may be inferred)
52
51
  def selected_operation_name
53
52
  return nil unless selected_operation
@@ -157,7 +156,7 @@ module GraphQL
157
156
  def result
158
157
  if !@executed
159
158
  with_prepared_ast {
160
- Execution::Multiplex.run_queries(@schema, [self], context: @context)
159
+ Execution::Multiplex.run_queries(@schema, [self])
161
160
  }
162
161
  end
163
162
  @result ||= Query::Result.new(query: self, values: @result_values)
@@ -194,8 +193,11 @@ module GraphQL
194
193
 
195
194
  def irep_selection
196
195
  @selection ||= begin
197
- return nil unless selected_operation
198
- internal_representation.operation_definitions[selected_operation.name]
196
+ if selected_operation && internal_representation
197
+ internal_representation.operation_definitions[selected_operation.name]
198
+ else
199
+ nil
200
+ end
199
201
  end
200
202
  end
201
203
 
@@ -238,6 +240,9 @@ module GraphQL
238
240
  value = abstract_type
239
241
  abstract_type = nil
240
242
  end
243
+ if value.is_a?(GraphQL::Schema::Object)
244
+ value = value.object
245
+ end
241
246
  @resolved_types_cache[abstract_type][value]
242
247
  end
243
248
 
@@ -12,40 +12,36 @@ module GraphQL
12
12
  argument_owner.arguments_class = Class.new(self) do
13
13
  self.argument_definitions = argument_definitions
14
14
 
15
- def initialize(values, defaults_used)
16
- super(values, argument_definitions: self.class.argument_definitions, defaults_used: defaults_used)
17
- end
18
-
19
15
  argument_definitions.each do |_arg_name, arg_definition|
20
16
  expose_as = arg_definition.expose_as.to_s
21
-
22
- # Don't define a helper method if it would override something.
23
- if instance_methods.include?(expose_as)
24
- warn(
25
- "Unable to define a helper for argument with name '#{expose_as}' "\
26
- "as this is a reserved name. If you're using an argument such as "\
27
- "`argument #{expose_as}`, consider renaming this argument.`"
28
- )
29
- next
30
- end
31
-
32
- define_method(expose_as) do
33
- self[expose_as]
17
+ expose_as_underscored = GraphQL::Schema::Member::BuildType.underscore(expose_as)
18
+ method_names = [expose_as, expose_as_underscored].uniq
19
+ method_names.each do |method_name|
20
+ # Don't define a helper method if it would override something.
21
+ if instance_methods.include?(method_name)
22
+ warn(
23
+ "Unable to define a helper for argument with name '#{method_name}' "\
24
+ "as this is a reserved name. If you're using an argument such as "\
25
+ "`argument #{method_name}`, consider renaming this argument.`"
26
+ )
27
+ else
28
+ define_method(method_name) do
29
+ # Always use `expose_as` here, since #[] doesn't accept underscored names
30
+ self[expose_as]
31
+ end
32
+ end
34
33
  end
35
34
  end
36
35
  end
37
36
  end
38
37
 
39
- def initialize(values, argument_definitions:, defaults_used:)
38
+ def initialize(values, context:)
40
39
  @argument_values = values.inject({}) do |memo, (inner_key, inner_value)|
41
- arg_name = inner_key.to_s
40
+ arg_defn = self.class.argument_definitions[inner_key.to_s]
42
41
 
43
- arg_defn = argument_definitions[arg_name]
44
- arg_default_used = defaults_used.include?(arg_name)
45
-
46
- arg_value = wrap_value(inner_value, arg_defn.type)
42
+ arg_value = wrap_value(inner_value, arg_defn.type, context)
47
43
  string_key = arg_defn.expose_as
48
- memo[string_key] = ArgumentValue.new(string_key, arg_value, arg_defn, arg_default_used)
44
+ memo[string_key] = ArgumentValue.new(string_key, arg_value, arg_defn)
49
45
  memo
50
46
  end
51
47
  end
@@ -64,13 +60,6 @@ module GraphQL
64
60
  @argument_values.key?(key_s)
65
61
  end
66
62
 
67
- # @param key [String, Symbol] name of value to access
68
- # @return [Boolean] true if the argument default was passed as the argument value to the resolver
69
- def default_used?(key)
70
- key_s = key.is_a?(String) ? key : key.to_s
71
- @argument_values.fetch(key_s, NULL_ARGUMENT_VALUE).default_used?
72
- end
73
-
74
63
  # Get the hash of all values, with stringified keys
75
64
  # @return [Hash] the stringified hash
76
65
  def to_h
@@ -84,7 +73,7 @@ module GraphQL
84
73
  end
85
74
  end
86
75
 
87
- def_delegators :to_h, :keys, :values, :each
76
+ def_delegators :to_h, :keys, :values, :each, :any?
88
77
 
89
78
  # Access each key, value and type for the arguments in this set.
90
79
  # @yield [argument_value] The {ArgumentValue} for each argument
@@ -95,45 +84,41 @@ module GraphQL
95
84
  end
96
85
  end
97
86
 
98
- NO_ARGS = self.new({}, argument_definitions: [], defaults_used: Set.new)
99
-
100
87
  class << self
101
88
  attr_accessor :argument_definitions
102
89
  end
103
90
 
91
+ NoArguments = Class.new(self) do
92
+ self.argument_definitions = []
93
+ end
94
+
95
+ NO_ARGS = NoArguments.new({}, context: nil)
96
+
104
97
  private
105
98
 
106
99
  class ArgumentValue
107
100
  attr_reader :key, :value, :definition
108
- attr_writer :default_used
109
-
110
- def initialize(key, value, definition, default_used)
101
+ def initialize(key, value, definition)
111
102
  @key = key
112
103
  @value = value
113
104
  @definition = definition
114
- @default_used = default_used
115
- end
116
-
117
- # @return [Boolean] true if the argument default was passed as the argument value to the resolver
118
- def default_used?
119
- @default_used
120
105
  end
121
106
  end
122
107
 
123
- NULL_ARGUMENT_VALUE = ArgumentValue.new(nil, nil, nil, nil)
108
+ NULL_ARGUMENT_VALUE = ArgumentValue.new(nil, nil, nil)
124
109
 
125
- def wrap_value(value, arg_defn_type)
110
+ def wrap_value(value, arg_defn_type, context)
126
111
  if value.nil?
127
112
  nil
128
113
  else
129
114
  case arg_defn_type
130
115
  when GraphQL::ListType
131
- value.map { |item| wrap_value(item, arg_defn_type.of_type) }
116
+ value.map { |item| wrap_value(item, arg_defn_type.of_type, context) }
132
117
  when GraphQL::NonNullType
133
- wrap_value(value, arg_defn_type.of_type)
118
+ wrap_value(value, arg_defn_type.of_type, context)
134
119
  when GraphQL::InputObjectType
135
120
  if value.is_a?(Hash)
136
- arg_defn_type.arguments_class.new(value, Set.new)
121
+ arg_defn_type.arguments_class.new(value, context: context)
137
122
  else
138
123
  value
139
124
  end
@@ -129,6 +129,7 @@ module GraphQL
129
129
  attr_writer :value
130
130
 
131
131
  def_delegators :@provided_values, :[], :[]=, :to_h, :key?, :fetch
132
+ def_delegators :@query, :trace
132
133
 
133
134
  # @!method [](key)
134
135
  # Lookup `key` from the hash passed to {Schema#execute} as `context:`
@@ -49,8 +49,6 @@ module GraphQL
49
49
  def self.from_arguments(ast_arguments, argument_owner, variables)
50
50
  context = variables ? variables.context : nil
51
51
  values_hash = {}
52
- defaults_used = Set.new
53
-
54
52
  indexed_arguments = case ast_arguments
55
53
  when Hash
56
54
  ast_arguments
@@ -95,7 +93,6 @@ module GraphQL
95
93
  # then add the default value.
96
94
  if arg_defn.default_value? && !values_hash.key?(arg_name)
97
95
  value = arg_defn.default_value
98
- defaults_used << arg_name
99
96
  # `context` isn't present when pre-calculating defaults
100
97
  if context
101
98
  value = arg_defn.prepare(value, context)
@@ -108,7 +105,7 @@ module GraphQL
108
105
  end
109
106
  end
110
107
 
111
- argument_owner.arguments_class.new(values_hash, defaults_used)
108
+ argument_owner.arguments_class.new(values_hash, context: context)
112
109
  end
113
110
  end
114
111
  end
@@ -41,6 +41,9 @@ module GraphQL
41
41
  ctx.add_error(nodes)
42
42
  nil
43
43
  else
44
+ if parent.is_a?(GraphQL::Schema::Object)
45
+ parent = parent.object
46
+ end
44
47
  connection_class = GraphQL::Relay::BaseConnection.connection_for_nodes(nodes)
45
48
  connection_class.new(nodes, args, field: @field, max_page_size: @max_page_size, parent: parent, context: ctx)
46
49
  end
@@ -7,7 +7,11 @@ module GraphQL
7
7
  end
8
8
 
9
9
  def call(obj, args, ctx)
10
- ctx.query.schema.id_from_object(obj, @type, ctx)
10
+ if obj.is_a?(GraphQL::Schema::Object)
11
+ obj = obj.object
12
+ end
13
+ type = @type.respond_to?(:graphql_definition) ? @type.graphql_definition : @type
14
+ ctx.query.schema.id_from_object(obj, type, ctx)
11
15
  end
12
16
  end
13
17
  end
@@ -7,11 +7,11 @@ module GraphQL
7
7
  # - `Sequel::Dataset`
8
8
  class RelationConnection < BaseConnection
9
9
  def cursor_from_node(item)
10
- item_index = paged_nodes.index(item)
10
+ item_index = paged_nodes_array.index(item)
11
11
  if item_index.nil?
12
12
  raise("Can't generate cursor, item not found in connection: #{item}")
13
13
  else
14
- offset = item_index + 1 + ((paged_nodes_offset || 0) - (relation_offset(sliced_nodes) || 0))
14
+ offset = item_index + 1 + ((relation_offset(paged_nodes) || 0) - (relation_offset(sliced_nodes) || 0))
15
15
 
16
16
  if after
17
17
  offset += offset_from_cursor(after)
@@ -25,9 +25,9 @@ module GraphQL
25
25
 
26
26
  def has_next_page
27
27
  if first
28
- paged_nodes.length >= first && sliced_nodes_count > first
28
+ paged_nodes_length >= first && sliced_nodes_count > first
29
29
  elsif GraphQL::Relay::ConnectionType.bidirectional_pagination && last
30
- sliced_nodes_count >= last
30
+ sliced_nodes_count > last
31
31
  else
32
32
  false
33
33
  end
@@ -35,7 +35,7 @@ module GraphQL
35
35
 
36
36
  def has_previous_page
37
37
  if last
38
- paged_nodes.length >= last && sliced_nodes_count > last
38
+ paged_nodes_length >= last && sliced_nodes_count > last
39
39
  elsif GraphQL::Relay::ConnectionType.bidirectional_pagination && after
40
40
  # We've already paginated through the collection a bit,
41
41
  # there are nodes behind us
@@ -64,7 +64,6 @@ module GraphQL
64
64
  private
65
65
 
66
66
  # apply first / last limit results
67
- # @return [Array]
68
67
  def paged_nodes
69
68
  return @paged_nodes if defined? @paged_nodes
70
69
 
@@ -95,14 +94,7 @@ module GraphQL
95
94
  end
96
95
  end
97
96
 
98
- # Store this here so we can convert the relation to an Array
99
- # (this avoids an extra DB call on Sequel)
100
- @paged_nodes_offset = relation_offset(items)
101
- @paged_nodes = items.to_a
102
- end
103
-
104
- def paged_nodes_offset
105
- paged_nodes && @paged_nodes_offset
97
+ @paged_nodes = items
106
98
  end
107
99
 
108
100
  def relation_offset(relation)
@@ -174,6 +166,19 @@ module GraphQL
174
166
  def offset_from_cursor(cursor)
175
167
  decode(cursor).to_i
176
168
  end
169
+
170
+ def paged_nodes_array
171
+ return @paged_nodes_array if defined?(@paged_nodes_array)
172
+ @paged_nodes_array = paged_nodes.to_a
173
+ end
174
+
175
+ def paged_nodes_length
176
+ if paged_nodes.respond_to?(:length)
177
+ paged_nodes.length
178
+ else
179
+ paged_nodes_array.length
180
+ end
181
+ end
177
182
  end
178
183
 
179
184
  if defined?(ActiveRecord::Relation)