Welcome to mirror list, hosted at ThFree Co, Russian Federation.

looks_ahead.rb « concerns « resolvers « graphql « app - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 81099c04e9f356430f95a05ecb792bdd79d097c9 (plain)
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
# frozen_string_literal: true

module LooksAhead
  extend ActiveSupport::Concern

  included do
    extras [:lookahead]
    attr_accessor :lookahead
  end

  def resolve(**args)
    self.lookahead = args.delete(:lookahead)

    resolve_with_lookahead(**args)
  end

  def apply_lookahead(query)
    all_preloads = (unconditional_includes + filtered_preloads).uniq

    return query if all_preloads.empty?

    query.preload(*all_preloads) # rubocop: disable CodeReuse/ActiveRecord
  end

  private

  def unconditional_includes
    []
  end

  def preloads
    {}
  end

  def nested_preloads
    {}
  end

  def filtered_preloads
    nodes = node_selection

    return [] unless nodes

    selected_fields = nodes.selections.map(&:name)
    root_level_preloads = preloads_from_node_selection(selected_fields, preloads)

    root_level_preloads + nested_filtered_preloads(nodes, selected_fields)
  end

  def nested_filtered_preloads(nodes, selected_root_fields)
    return [] if nested_preloads.empty?

    nested_preloads.each_with_object([]) do |(root_field, fields), result|
      next unless selected_root_fields.include?(root_field)

      selected_fields = nodes.selection(root_field).selections.map(&:name)

      result << preloads_from_node_selection(selected_fields, fields)
    end.flatten
  end

  def preloads_from_node_selection(selected_fields, fields)
    fields.each_with_object([]) do |(field, requirements), result|
      result << requirements if selected_fields.include?(field)
    end.flatten
  end

  def node_selection
    return unless lookahead

    if lookahead.selects?(:nodes)
      lookahead.selection(:nodes)
    elsif lookahead.selects?(:edges)
      lookahead.selection(:edges).selection(:node)
    end
  end
end