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

design_at_version.rb « design_management « models « app - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 211211144f4ea164bddd722c321e22776c309a18 (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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# frozen_string_literal: true

# Tuple of design and version
# * has a composite ID, with lazy_find
module DesignManagement
  class DesignAtVersion
    include ActiveModel::Validations
    include GlobalID::Identification
    include Gitlab::Utils::StrongMemoize

    attr_reader :version
    attr_reader :design

    validates :version, presence: true
    validates :design, presence: true

    validate :design_and_version_belong_to_the_same_issue
    validate :design_and_version_have_issue_id

    def initialize(design: nil, version: nil)
      @design, @version = design, version
    end

    # The ID, needed by GraphQL types and as part of the Lazy-fetch
    # protocol, includes information about both the design and the version.
    #
    # The particular format is not interesting, and should be treated as opaque
    # by all callers.
    def id
      "#{design.id}.#{version.id}"
    end

    def ==(other)
      return false unless other && self.class == other.class

      other.id == id
    end

    alias_method :eql?, :==

    def self.lazy_find(id)
      BatchLoader.for(id).batch do |ids, callback|
        find(ids).each do |record|
          callback.call(record.id, record)
        end
      end
    end

    def self.find(ids)
      pairs = ids.map { |id| id.split('.').map(&:to_i) }

      design_ids = pairs.map(&:first).uniq
      version_ids = pairs.map(&:second).uniq

      designs = ::DesignManagement::Design
        .where(id: design_ids)
        .index_by(&:id)

      versions = ::DesignManagement::Version
        .where(id: version_ids)
        .index_by(&:id)

      pairs.map do |(design_id, version_id)|
        design = designs[design_id]
        version = versions[version_id]

        obj = new(design: design, version: version)

        obj if obj.valid?
      end.compact
    end

    def status
      if not_created_yet?
        :not_created_yet
      elsif deleted?
        :deleted
      else
        :current
      end
    end

    def deleted?
      action&.deletion?
    end

    def not_created_yet?
      action.nil?
    end

    private

    def action
      strong_memoize(:most_recent_action) do
        ::DesignManagement::Action
          .most_recent.up_to_version(version)
          .find_by(design: design)
      end
    end

    def design_and_version_belong_to_the_same_issue
      id_a, id_b = [design, version].map { |obj| obj&.issue_id }

      return if id_a == id_b

      errors.add(:issue, 'must be the same on design and version')
    end

    def design_and_version_have_issue_id
      return if [design, version].all? { |obj| obj.try(:issue_id).present? }

      errors.add(:issue, 'must be present on both design and version')
    end
  end
end