diff --git a/lib/graphql/compatibility/lazy_execution_specification.rb b/lib/graphql/compatibility/lazy_execution_specification.rb index a5700af7ed..db835b45d3 100644 --- a/lib/graphql/compatibility/lazy_execution_specification.rb +++ b/lib/graphql/compatibility/lazy_execution_specification.rb @@ -108,6 +108,34 @@ def test_it_resolves_mutation_values_eagerly ] assert_equal expected_pushes, pushes end + + def test_it_resolves_lazy_connections + pushes = [] + query_str = %| + { + pushes(values: [1,2,3]) { + edges { + node { + value + push(value: 4) { + value + } + } + } + } + } + | + res = self.class.lazy_schema.execute(query_str, context: {pushes: pushes}) + + expected_edges = [ + {"node"=>{"value"=>1, "push"=>{"value"=>4}}}, + {"node"=>{"value"=>2, "push"=>{"value"=>4}}}, + {"node"=>{"value"=>3, "push"=>{"value"=>4}}}, + ] + assert_equal expected_edges, res["data"]["pushes"]["edges"] + assert_equal [[1, 2, 3], [4, 4, 4]], pushes + + end end end end diff --git a/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb b/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb index 5b43732985..f4a8bab38b 100644 --- a/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +++ b/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb @@ -26,6 +26,17 @@ def push end end + class LazyPushCollection + def initialize(ctx, values) + @ctx = ctx + @values = values + end + + def push + @values.map { |v| LazyPush.new(@ctx, v) } + end + end + def self.build(execution_strategy) lazy_push_type = GraphQL::ObjectType.define do name "LazyPush" @@ -46,6 +57,13 @@ def self.build(execution_strategy) LazyPush.new(c, a[:value]) } end + + connection :pushes, lazy_push_type.connection_type do + argument :values, types[types.Int] + resolve ->(o, a, c) { + LazyPushCollection.new(c, a[:values]) + } + end end GraphQL::Schema.define do @@ -54,6 +72,7 @@ def self.build(execution_strategy) query_execution_strategy(execution_strategy) mutation_execution_strategy(execution_strategy) lazy_resolve(LazyPush, :push) + lazy_resolve(LazyPushCollection, :push) end end end diff --git a/lib/graphql/execution/execute.rb b/lib/graphql/execution/execute.rb index b0169a1c10..202a132016 100644 --- a/lib/graphql/execution/execute.rb +++ b/lib/graphql/execution/execute.rb @@ -76,7 +76,11 @@ def resolve_field(owner, selection, parent_type, field, object, query_ctx) lazy_method_name = query.lazy_method(raw_value) result = if lazy_method_name - GraphQL::Execution::Lazy.new { raw_value.public_send(lazy_method_name) }.then { |inner_value| + GraphQL::Execution::Lazy.new(raw_value, lazy_method_name).then { |inner_value| + continue_resolve_field(selection, parent_type, field, inner_value, field_ctx) + } + elsif raw_value.is_a?(GraphQL::Execution::Lazy) + raw_value.then { |inner_value| continue_resolve_field(selection, parent_type, field, inner_value, field_ctx) } else diff --git a/lib/graphql/execution/lazy.rb b/lib/graphql/execution/lazy.rb index 6b7323aee0..5ffed71b6d 100644 --- a/lib/graphql/execution/lazy.rb +++ b/lib/graphql/execution/lazy.rb @@ -18,9 +18,16 @@ def self.resolve(val) end # Create a {Lazy} which will get its inner value by calling the block + # @param target [Object] + # @param method_name [Symbol] # @param get_value_func [Proc] a block to get the inner value (later) - def initialize(&get_value_func) - @get_value_func = get_value_func + def initialize(target = nil, method_name = nil, &get_value_func) + if block_given? + @get_value_func = get_value_func + else + @target = target + @method_name = method_name + end @resolved = false end @@ -28,7 +35,11 @@ def initialize(&get_value_func) def value if !@resolved @resolved = true - @value = @get_value_func.call + if @get_value_func + @value = @get_value_func.call + else + @value = @target.public_send(@method_name) + end end @value rescue GraphQL::ExecutionError => err diff --git a/lib/graphql/relay/connection_resolve.rb b/lib/graphql/relay/connection_resolve.rb index e4222ef988..e5288fa48f 100644 --- a/lib/graphql/relay/connection_resolve.rb +++ b/lib/graphql/relay/connection_resolve.rb @@ -9,8 +9,22 @@ def initialize(field, underlying_resolve, max_page_size: nil) def call(obj, args, ctx) nodes = @underlying_resolve.call(obj, args, ctx) + lazy_method = ctx.query.lazy_method(nodes) + if lazy_method + GraphQL::Execution::Lazy.new do + resolved_nodes = nodes.public_send(lazy_method) + build_connection(resolved_nodes, args, obj) + end + else + build_connection(nodes, args, obj) + end + end + + private + + def build_connection(nodes, args, parent) connection_class = GraphQL::Relay::BaseConnection.connection_for_nodes(nodes) - connection_class.new(nodes, args, field: @field, max_page_size: @max_page_size, parent: obj) + connection_class.new(nodes, args, field: @field, max_page_size: @max_page_size, parent: parent) end end end