summaryrefslogtreecommitdiff
path: root/lib/api/projects_relation_builder.rb
blob: fb782b49f02958c76f53caadfc57d88b9b045552 (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
# frozen_string_literal: true

module API
  module ProjectsRelationBuilder
    extend ActiveSupport::Concern

    class_methods do
      def prepare_relation(projects_relation, options = {})
        projects_relation = preload_relation(projects_relation, options)

        execute_batch_counting(projects_relation)

        preload_repository_cache(projects_relation)

        Preloaders::UserMaxAccessLevelInProjectsPreloader.new(projects_relation, options[:current_user]).execute if options[:current_user]
        Preloaders::SingleHierarchyProjectGroupPlansPreloader.new(projects_relation).execute if options[:single_hierarchy]
        preload_groups(projects_relation) if options[:with] == Entities::Project

        projects_relation
      end

      # This is overridden by the specific Entity class to
      # preload assocations that it needs
      def preload_relation(projects_relation, options = {})
        projects_relation
      end

      # This is overridden by the specific Entity class to
      # batch load certain counts
      def execute_batch_counting(projects_relation)
      end

      def preload_repository_cache(projects_relation)
        repositories = repositories_for_preload(projects_relation)

        Gitlab::RepositoryCache::Preloader.new(repositories).preload( # rubocop:disable CodeReuse/ActiveRecord
          %i[exists? root_ref has_visible_content? avatar readme_path]
        )
      end

      def repositories_for_preload(projects_relation)
        projects_relation.map(&:repository)
      end

      # For all projects except those in a user namespace, the `namespace`
      # and `group` are identical. Preload the group when it's not a user namespace.
      def preload_groups(projects_relation)
        group_projects = projects_for_group_preload(projects_relation)
        groups = group_projects.map(&:namespace)

        Preloaders::GroupRootAncestorPreloader.new(groups).execute

        group_projects.each do |project|
          project.group = project.namespace
        end
      end

      def projects_for_group_preload(projects_relation)
        projects_relation.select { |project| project.namespace.type == Group.sti_name }
      end
    end
  end
end