graphql 1.12.3 → 1.12.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of graphql might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/lib/generators/graphql/install_generator.rb +4 -1
- data/lib/generators/graphql/loader_generator.rb +1 -0
- data/lib/generators/graphql/mutation_generator.rb +1 -0
- data/lib/generators/graphql/relay.rb +55 -0
- data/lib/generators/graphql/relay_generator.rb +4 -46
- data/lib/generators/graphql/type_generator.rb +1 -0
- data/lib/graphql.rb +4 -2
- data/lib/graphql/backtrace/inspect_result.rb +0 -1
- data/lib/graphql/backtrace/table.rb +0 -1
- data/lib/graphql/backtrace/traced_error.rb +0 -1
- data/lib/graphql/backtrace/tracer.rb +4 -8
- data/lib/graphql/dataloader.rb +102 -92
- data/lib/graphql/dataloader/null_dataloader.rb +5 -5
- data/lib/graphql/dataloader/request.rb +1 -6
- data/lib/graphql/dataloader/request_all.rb +1 -4
- data/lib/graphql/dataloader/source.rb +20 -6
- data/lib/graphql/execution/errors.rb +109 -11
- data/lib/graphql/execution/interpreter.rb +2 -2
- data/lib/graphql/execution/interpreter/arguments_cache.rb +37 -14
- data/lib/graphql/execution/interpreter/resolve.rb +33 -25
- data/lib/graphql/execution/interpreter/runtime.rb +41 -78
- data/lib/graphql/execution/multiplex.rb +21 -22
- data/lib/graphql/introspection.rb +1 -1
- data/lib/graphql/introspection/directive_type.rb +7 -3
- data/lib/graphql/language.rb +1 -0
- data/lib/graphql/language/cache.rb +37 -0
- data/lib/graphql/language/parser.rb +15 -5
- data/lib/graphql/language/parser.y +15 -5
- data/lib/graphql/object_type.rb +0 -2
- data/lib/graphql/pagination/active_record_relation_connection.rb +7 -0
- data/lib/graphql/pagination/connection.rb +15 -1
- data/lib/graphql/pagination/connections.rb +1 -0
- data/lib/graphql/pagination/relation_connection.rb +12 -1
- data/lib/graphql/parse_error.rb +0 -1
- data/lib/graphql/query.rb +9 -5
- data/lib/graphql/query/arguments_cache.rb +0 -1
- data/lib/graphql/query/context.rb +1 -3
- data/lib/graphql/query/executor.rb +0 -1
- data/lib/graphql/query/null_context.rb +3 -2
- data/lib/graphql/query/validation_pipeline.rb +1 -1
- data/lib/graphql/query/variable_validation_error.rb +1 -1
- data/lib/graphql/railtie.rb +9 -1
- data/lib/graphql/relay/range_add.rb +10 -5
- data/lib/graphql/schema.rb +14 -27
- data/lib/graphql/schema/argument.rb +61 -0
- data/lib/graphql/schema/field.rb +10 -5
- data/lib/graphql/schema/field/connection_extension.rb +1 -0
- data/lib/graphql/schema/find_inherited_value.rb +3 -1
- data/lib/graphql/schema/input_object.rb +6 -2
- data/lib/graphql/schema/member/has_arguments.rb +43 -56
- data/lib/graphql/schema/member/has_fields.rb +1 -4
- data/lib/graphql/schema/member/instrumentation.rb +0 -1
- data/lib/graphql/schema/resolver.rb +28 -1
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +3 -1
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +6 -2
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +2 -1
- data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +4 -2
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +2 -2
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +0 -3
- data/lib/graphql/subscriptions/event.rb +0 -1
- data/lib/graphql/subscriptions/instrumentation.rb +0 -1
- data/lib/graphql/subscriptions/serialize.rb +3 -1
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +2 -1
- data/lib/graphql/types/relay/base_connection.rb +4 -0
- data/lib/graphql/types/relay/connection_behaviors.rb +38 -5
- data/lib/graphql/types/relay/edge_behaviors.rb +12 -1
- data/lib/graphql/version.rb +1 -1
- data/readme.md +1 -1
- metadata +8 -90
@@ -56,17 +56,18 @@ module GraphQL
|
|
56
56
|
# Root .authorized? returned false.
|
57
57
|
write_in_response(path, nil)
|
58
58
|
else
|
59
|
-
|
60
|
-
@progress_path = path
|
61
|
-
@progress_scoped_context = context.scoped_context
|
62
|
-
@progress_object = object_proxy
|
63
|
-
@progress_object_type = root_type
|
64
|
-
@progress_index = nil
|
65
|
-
@progress_is_eager_selection = root_op_type == "mutation"
|
66
|
-
@progress_selections = gather_selections(object_proxy, root_type, root_operation.selections)
|
67
|
-
|
59
|
+
gathered_selections = gather_selections(object_proxy, root_type, root_operation.selections)
|
68
60
|
# Make the first fiber which will begin execution
|
69
|
-
|
61
|
+
@dataloader.append_job {
|
62
|
+
evaluate_selections(
|
63
|
+
path,
|
64
|
+
context.scoped_context,
|
65
|
+
object_proxy,
|
66
|
+
root_type,
|
67
|
+
root_op_type == "mutation",
|
68
|
+
gathered_selections,
|
69
|
+
)
|
70
|
+
}
|
70
71
|
end
|
71
72
|
delete_interpreter_context(:current_path)
|
72
73
|
delete_interpreter_context(:current_field)
|
@@ -75,32 +76,6 @@ module GraphQL
|
|
75
76
|
nil
|
76
77
|
end
|
77
78
|
|
78
|
-
# Use `@dataloader` to enqueue a fiber that will pick up from the current point.
|
79
|
-
# @return [void]
|
80
|
-
def enqueue_selections_fiber
|
81
|
-
# Read these into local variables so that later assignments don't affect the block below.
|
82
|
-
path = @progress_path
|
83
|
-
scoped_context = @progress_scoped_context
|
84
|
-
owner_object = @progress_object
|
85
|
-
owner_type = @progress_object_type
|
86
|
-
idx = @progress_index
|
87
|
-
is_eager_selection = @progress_is_eager_selection
|
88
|
-
gathered_selections = @progress_selections
|
89
|
-
|
90
|
-
@dataloader.enqueue {
|
91
|
-
evaluate_selections(
|
92
|
-
path,
|
93
|
-
scoped_context,
|
94
|
-
owner_object,
|
95
|
-
owner_type,
|
96
|
-
is_eager_selection: is_eager_selection,
|
97
|
-
after: idx,
|
98
|
-
gathered_selections: gathered_selections,
|
99
|
-
)
|
100
|
-
}
|
101
|
-
nil
|
102
|
-
end
|
103
|
-
|
104
79
|
def gather_selections(owner_object, owner_type, selections, selections_by_name = {})
|
105
80
|
selections.each do |node|
|
106
81
|
# Skip gathering this if the directive says so
|
@@ -159,39 +134,17 @@ module GraphQL
|
|
159
134
|
NO_ARGS = {}.freeze
|
160
135
|
|
161
136
|
# @return [void]
|
162
|
-
def evaluate_selections(path, scoped_context, owner_object, owner_type, is_eager_selection
|
137
|
+
def evaluate_selections(path, scoped_context, owner_object, owner_type, is_eager_selection, gathered_selections)
|
163
138
|
set_all_interpreter_context(owner_object, nil, nil, path)
|
164
139
|
|
165
|
-
@progress_path = path
|
166
|
-
@progress_scoped_context = scoped_context
|
167
|
-
@progress_object = owner_object
|
168
|
-
@progress_object_type = owner_type
|
169
|
-
@progress_index = nil
|
170
|
-
@progress_is_eager_selection = is_eager_selection
|
171
|
-
@progress_selections = gathered_selections
|
172
|
-
|
173
|
-
# Track `idx` manually to avoid an allocation on this hot path
|
174
|
-
idx = 0
|
175
140
|
gathered_selections.each do |result_name, field_ast_nodes_or_ast_node|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
if after && prev_idx <= after
|
182
|
-
next
|
183
|
-
end
|
184
|
-
@progress_index = prev_idx
|
185
|
-
# This is how the current runtime gives itself to `dataloader`
|
186
|
-
# so that the dataloader can enqueue another fiber to resume if needed.
|
187
|
-
@dataloader.current_runtime = self
|
188
|
-
evaluate_selection(path, result_name, field_ast_nodes_or_ast_node, scoped_context, owner_object, owner_type, is_eager_selection)
|
189
|
-
# The dataloader knows if ^^ that selection halted and later selections were executed in another fiber.
|
190
|
-
# If that's the case, then don't continue execution here.
|
191
|
-
if @dataloader.yielded?(path)
|
192
|
-
break
|
193
|
-
end
|
141
|
+
@dataloader.append_job {
|
142
|
+
evaluate_selection(
|
143
|
+
path, result_name, field_ast_nodes_or_ast_node, scoped_context, owner_object, owner_type, is_eager_selection
|
144
|
+
)
|
145
|
+
}
|
194
146
|
end
|
147
|
+
|
195
148
|
nil
|
196
149
|
end
|
197
150
|
|
@@ -243,13 +196,21 @@ module GraphQL
|
|
243
196
|
object = authorized_new(field_defn.owner, object, context, next_path)
|
244
197
|
end
|
245
198
|
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
199
|
+
total_args_count = field_defn.arguments.size
|
200
|
+
if total_args_count == 0
|
201
|
+
kwarg_arguments = GraphQL::Execution::Interpreter::Arguments::EMPTY
|
202
|
+
evaluate_selection_with_args(kwarg_arguments, field_defn, next_path, ast_node, field_ast_nodes, scoped_context, owner_type, object, is_eager_field)
|
203
|
+
else
|
204
|
+
# TODO remove all arguments(...) usages?
|
205
|
+
@query.arguments_cache.dataload_for(ast_node, field_defn, object) do |resolved_arguments|
|
206
|
+
evaluate_selection_with_args(resolved_arguments, field_defn, next_path, ast_node, field_ast_nodes, scoped_context, owner_type, object, is_eager_field)
|
207
|
+
end
|
251
208
|
end
|
209
|
+
end
|
252
210
|
|
211
|
+
def evaluate_selection_with_args(kwarg_arguments, field_defn, next_path, ast_node, field_ast_nodes, scoped_context, owner_type, object, is_eager_field) # rubocop:disable Metrics/ParameterLists
|
212
|
+
context.scoped_context = scoped_context
|
213
|
+
return_type = field_defn.type
|
253
214
|
after_lazy(kwarg_arguments, owner: owner_type, field: field_defn, path: next_path, ast_node: ast_node, scoped_context: context.scoped_context, owner_object: object, arguments: kwarg_arguments) do |resolved_arguments|
|
254
215
|
if resolved_arguments.is_a?(GraphQL::ExecutionError) || resolved_arguments.is_a?(GraphQL::UnauthorizedError)
|
255
216
|
continue_value(next_path, resolved_arguments, owner_type, field_defn, return_type.non_null?, ast_node)
|
@@ -316,10 +277,7 @@ module GraphQL
|
|
316
277
|
end
|
317
278
|
after_lazy(app_result, owner: owner_type, field: field_defn, path: next_path, ast_node: ast_node, scoped_context: context.scoped_context, owner_object: object, arguments: kwarg_arguments) do |inner_result|
|
318
279
|
continue_value = continue_value(next_path, inner_result, owner_type, field_defn, return_type.non_null?, ast_node)
|
319
|
-
if
|
320
|
-
# Write raw value directly to the response without resolving nested objects
|
321
|
-
write_in_response(next_path, continue_value.resolve)
|
322
|
-
elsif HALT != continue_value
|
280
|
+
if HALT != continue_value
|
323
281
|
continue_field(next_path, continue_value, owner_type, field_defn, return_type, ast_node, next_selections, false, object, kwarg_arguments)
|
324
282
|
end
|
325
283
|
end
|
@@ -329,10 +287,11 @@ module GraphQL
|
|
329
287
|
# all of its child fields before moving on to the next root mutation field.
|
330
288
|
# (Subselections of this mutation will still be resolved level-by-level.)
|
331
289
|
if is_eager_field
|
332
|
-
Interpreter::Resolve.resolve_all([field_result])
|
290
|
+
Interpreter::Resolve.resolve_all([field_result], @dataloader)
|
291
|
+
else
|
292
|
+
# Return this from `after_lazy` because it might be another lazy that needs to be resolved
|
293
|
+
field_result
|
333
294
|
end
|
334
|
-
|
335
|
-
nil
|
336
295
|
end
|
337
296
|
end
|
338
297
|
|
@@ -370,6 +329,10 @@ module GraphQL
|
|
370
329
|
continue_value(path, next_value, parent_type, field, is_non_null, ast_node)
|
371
330
|
elsif GraphQL::Execution::Execute::SKIP == value
|
372
331
|
HALT
|
332
|
+
elsif value.is_a?(GraphQL::Execution::Interpreter::RawValue)
|
333
|
+
# Write raw value directly to the response without resolving nested objects
|
334
|
+
write_in_response(path, value.resolve)
|
335
|
+
HALT
|
373
336
|
else
|
374
337
|
value
|
375
338
|
end
|
@@ -419,7 +382,7 @@ module GraphQL
|
|
419
382
|
response_hash = {}
|
420
383
|
write_in_response(path, response_hash)
|
421
384
|
gathered_selections = gather_selections(continue_value, current_type, next_selections)
|
422
|
-
evaluate_selections(path, context.scoped_context, continue_value, current_type,
|
385
|
+
evaluate_selections(path, context.scoped_context, continue_value, current_type, false, gathered_selections)
|
423
386
|
response_hash
|
424
387
|
end
|
425
388
|
end
|
@@ -35,7 +35,7 @@ module GraphQL
|
|
35
35
|
@queries = queries
|
36
36
|
@queries.each { |q| q.multiplex = self }
|
37
37
|
@context = context
|
38
|
-
@context[:dataloader] = @dataloader = @schema.dataloader_class.new
|
38
|
+
@context[:dataloader] = @dataloader = @schema.dataloader_class.new
|
39
39
|
@tracers = schema.tracers + (context[:tracers] || [])
|
40
40
|
# Support `context: {backtrace: true}`
|
41
41
|
if context[:backtrace] && !@tracers.include?(GraphQL::Backtrace::Tracer)
|
@@ -74,6 +74,24 @@ module GraphQL
|
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
+
# @param query [GraphQL::Query]
|
78
|
+
def begin_query(results, idx, query, multiplex)
|
79
|
+
operation = query.selected_operation
|
80
|
+
result = if operation.nil? || !query.valid? || query.context.errors.any?
|
81
|
+
NO_OPERATION
|
82
|
+
else
|
83
|
+
begin
|
84
|
+
# These were checked to be the same in `#supports_multiplexing?`
|
85
|
+
query.schema.query_execution_strategy.begin_query(query, multiplex)
|
86
|
+
rescue GraphQL::ExecutionError => err
|
87
|
+
query.context.errors << err
|
88
|
+
NO_OPERATION
|
89
|
+
end
|
90
|
+
end
|
91
|
+
results[idx] = result
|
92
|
+
nil
|
93
|
+
end
|
94
|
+
|
77
95
|
private
|
78
96
|
|
79
97
|
def run_as_multiplex(multiplex)
|
@@ -83,15 +101,13 @@ module GraphQL
|
|
83
101
|
# Do as much eager evaluation of the query as possible
|
84
102
|
results = []
|
85
103
|
queries.each_with_index do |query, idx|
|
86
|
-
multiplex.dataloader.
|
87
|
-
results[idx] = begin_query(query, multiplex)
|
88
|
-
}
|
104
|
+
multiplex.dataloader.append_job { begin_query(results, idx, query, multiplex) }
|
89
105
|
end
|
90
106
|
|
91
107
|
multiplex.dataloader.run
|
92
108
|
|
93
109
|
# Then, work through lazy results in a breadth-first way
|
94
|
-
multiplex.dataloader.
|
110
|
+
multiplex.dataloader.append_job {
|
95
111
|
multiplex.schema.query_execution_strategy.finish_multiplex(results, multiplex)
|
96
112
|
}
|
97
113
|
multiplex.dataloader.run
|
@@ -112,23 +128,6 @@ module GraphQL
|
|
112
128
|
raise
|
113
129
|
end
|
114
130
|
|
115
|
-
# @param query [GraphQL::Query]
|
116
|
-
# @return [Hash] The initial result (may not be finished if there are lazy values)
|
117
|
-
def begin_query(query, multiplex)
|
118
|
-
operation = query.selected_operation
|
119
|
-
if operation.nil? || !query.valid? || query.context.errors.any?
|
120
|
-
NO_OPERATION
|
121
|
-
else
|
122
|
-
begin
|
123
|
-
# These were checked to be the same in `#supports_multiplexing?`
|
124
|
-
query.schema.query_execution_strategy.begin_query(query, multiplex)
|
125
|
-
rescue GraphQL::ExecutionError => err
|
126
|
-
query.context.errors << err
|
127
|
-
NO_OPERATION
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
131
|
# @param data_result [Hash] The result for the "data" key, if any
|
133
132
|
# @param query [GraphQL::Query] The query which was run
|
134
133
|
# @return [Hash] final result of this query, including all values and errors
|
@@ -12,13 +12,17 @@ module GraphQL
|
|
12
12
|
field :name, String, null: false, method: :graphql_name
|
13
13
|
field :description, String, null: true
|
14
14
|
field :locations, [GraphQL::Schema::LateBoundType.new("__DirectiveLocation")], null: false
|
15
|
-
field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false
|
15
|
+
field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false do
|
16
|
+
argument :include_deprecated, Boolean, required: false, default_value: false
|
17
|
+
end
|
16
18
|
field :on_operation, Boolean, null: false, deprecation_reason: "Use `locations`.", method: :on_operation?
|
17
19
|
field :on_fragment, Boolean, null: false, deprecation_reason: "Use `locations`.", method: :on_fragment?
|
18
20
|
field :on_field, Boolean, null: false, deprecation_reason: "Use `locations`.", method: :on_field?
|
19
21
|
|
20
|
-
def args
|
21
|
-
@context.warden.arguments(@object)
|
22
|
+
def args(include_deprecated:)
|
23
|
+
args = @context.warden.arguments(@object)
|
24
|
+
args = args.reject(&:deprecation_reason) unless include_deprecated
|
25
|
+
args
|
22
26
|
end
|
23
27
|
end
|
24
28
|
end
|
data/lib/graphql/language.rb
CHANGED
@@ -6,6 +6,7 @@ require "graphql/language/document_from_schema_definition"
|
|
6
6
|
require "graphql/language/generation"
|
7
7
|
require "graphql/language/lexer"
|
8
8
|
require "graphql/language/nodes"
|
9
|
+
require "graphql/language/cache"
|
9
10
|
require "graphql/language/parser"
|
10
11
|
require "graphql/language/token"
|
11
12
|
require "graphql/language/visitor"
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'graphql/version'
|
4
|
+
require 'digest/sha2'
|
5
|
+
|
6
|
+
module GraphQL
|
7
|
+
module Language
|
8
|
+
class Cache
|
9
|
+
def initialize(path)
|
10
|
+
@path = path
|
11
|
+
end
|
12
|
+
|
13
|
+
DIGEST = Digest::SHA256.new << GraphQL::VERSION
|
14
|
+
def fetch(filename)
|
15
|
+
hash = DIGEST.dup << filename
|
16
|
+
begin
|
17
|
+
hash << File.mtime(filename).to_i.to_s
|
18
|
+
rescue SystemCallError
|
19
|
+
return yield
|
20
|
+
end
|
21
|
+
cache_path = @path.join(hash.to_s)
|
22
|
+
|
23
|
+
if cache_path.exist?
|
24
|
+
Marshal.load(cache_path.read)
|
25
|
+
else
|
26
|
+
payload = yield
|
27
|
+
tmp_path = "#{cache_path}.#{rand}"
|
28
|
+
|
29
|
+
@path.mkpath
|
30
|
+
File.binwrite(tmp_path, Marshal.dump(payload))
|
31
|
+
File.rename(tmp_path, cache_path.to_s)
|
32
|
+
payload
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -41,12 +41,22 @@ def parse_document
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
-
|
45
|
-
|
46
|
-
|
44
|
+
class << self
|
45
|
+
attr_accessor :cache
|
46
|
+
|
47
|
+
def parse(query_string, filename: nil, tracer: GraphQL::Tracing::NullTracer)
|
48
|
+
new(query_string, filename: filename, tracer: tracer).parse_document
|
49
|
+
end
|
47
50
|
|
48
|
-
def
|
49
|
-
|
51
|
+
def parse_file(filename, tracer: GraphQL::Tracing::NullTracer)
|
52
|
+
if cache
|
53
|
+
cache.fetch(filename) do
|
54
|
+
parse(File.read(filename), filename: filename, tracer: tracer)
|
55
|
+
end
|
56
|
+
else
|
57
|
+
parse(File.read(filename), filename: filename, tracer: tracer)
|
58
|
+
end
|
59
|
+
end
|
50
60
|
end
|
51
61
|
|
52
62
|
private
|
@@ -462,12 +462,22 @@ def parse_document
|
|
462
462
|
end
|
463
463
|
end
|
464
464
|
|
465
|
-
|
466
|
-
|
467
|
-
|
465
|
+
class << self
|
466
|
+
attr_accessor :cache
|
467
|
+
|
468
|
+
def parse(query_string, filename: nil, tracer: GraphQL::Tracing::NullTracer)
|
469
|
+
new(query_string, filename: filename, tracer: tracer).parse_document
|
470
|
+
end
|
468
471
|
|
469
|
-
def
|
470
|
-
|
472
|
+
def parse_file(filename, tracer: GraphQL::Tracing::NullTracer)
|
473
|
+
if cache
|
474
|
+
cache.fetch(filename) do
|
475
|
+
parse(File.read(filename), filename: filename, tracer: tracer)
|
476
|
+
end
|
477
|
+
else
|
478
|
+
parse(File.read(filename), filename: filename, tracer: tracer)
|
479
|
+
end
|
480
|
+
end
|
471
481
|
end
|
472
482
|
|
473
483
|
private
|
data/lib/graphql/object_type.rb
CHANGED
@@ -121,8 +121,6 @@ module GraphQL
|
|
121
121
|
iface = GraphQL::BaseType.resolve_related_type(type_membership.abstract_type)
|
122
122
|
if iface.is_a?(GraphQL::InterfaceType)
|
123
123
|
@clean_inherited_fields.merge!(iface.fields)
|
124
|
-
else
|
125
|
-
pp iface
|
126
124
|
end
|
127
125
|
end
|
128
126
|
@clean_inherited_fields
|
@@ -5,6 +5,13 @@ module GraphQL
|
|
5
5
|
module Pagination
|
6
6
|
# Customizes `RelationConnection` to work with `ActiveRecord::Relation`s.
|
7
7
|
class ActiveRecordRelationConnection < Pagination::RelationConnection
|
8
|
+
private
|
9
|
+
|
10
|
+
def relation_larger_than(relation, size)
|
11
|
+
initial_offset = relation.offset_value || 0
|
12
|
+
relation.offset(initial_offset + size).exists?
|
13
|
+
end
|
14
|
+
|
8
15
|
def relation_count(relation)
|
9
16
|
int_or_hash = if relation.respond_to?(:unscope)
|
10
17
|
relation.unscope(:order).count(:all)
|
@@ -45,6 +45,9 @@ module GraphQL
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
+
# @return [Hash<Symbol => Object>] The field arguments from the field that returned this connection
|
49
|
+
attr_accessor :arguments
|
50
|
+
|
48
51
|
# @param items [Object] some unpaginated collection item, like an `Array` or `ActiveRecord::Relation`
|
49
52
|
# @param context [Query::Context]
|
50
53
|
# @param parent [Object] The object this collection belongs to
|
@@ -52,8 +55,9 @@ module GraphQL
|
|
52
55
|
# @param after [String, nil] A cursor for pagination, if the client provided one
|
53
56
|
# @param last [Integer, nil] Limit parameter from the client, if provided
|
54
57
|
# @param before [String, nil] A cursor for pagination, if the client provided one.
|
58
|
+
# @param arguments [Hash] The arguments to the field that returned the collection wrapped by this connection
|
55
59
|
# @param max_page_size [Integer, nil] A configured value to cap the result size. Applied as `first` if neither first or last are given.
|
56
|
-
def initialize(items, parent: nil, field: nil, context: nil, first: nil, after: nil, max_page_size: :not_given, last: nil, before: nil, edge_class: nil)
|
60
|
+
def initialize(items, parent: nil, field: nil, context: nil, first: nil, after: nil, max_page_size: :not_given, last: nil, before: nil, edge_class: nil, arguments: nil)
|
57
61
|
@items = items
|
58
62
|
@parent = parent
|
59
63
|
@context = context
|
@@ -62,6 +66,7 @@ module GraphQL
|
|
62
66
|
@after_value = after
|
63
67
|
@last_value = last
|
64
68
|
@before_value = before
|
69
|
+
@arguments = arguments
|
65
70
|
@edge_class = edge_class || self.class::Edge
|
66
71
|
# This is only true if the object was _initialized_ with an override
|
67
72
|
# or if one is assigned later.
|
@@ -105,6 +110,15 @@ module GraphQL
|
|
105
110
|
end
|
106
111
|
end
|
107
112
|
|
113
|
+
# This is called by `Relay::RangeAdd` -- it can be overridden
|
114
|
+
# when `item` needs some modifications based on this connection's state.
|
115
|
+
#
|
116
|
+
# @param item [Object] An item newly added to `items`
|
117
|
+
# @return [Edge]
|
118
|
+
def range_add_edge(item)
|
119
|
+
edge_class.new(item, self)
|
120
|
+
end
|
121
|
+
|
108
122
|
attr_writer :last
|
109
123
|
# @return [Integer, nil] A clamped `last` value. (The underlying instance variable doesn't have limits on it)
|
110
124
|
def last
|