summaryrefslogtreecommitdiff
path: root/app/models/discussion.rb
blob: 782db4044ed399b8c8368acefba496faceabcd58 (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
class Discussion
  cattr_accessor :memoized_values, instance_accessor: false do
    []
  end

  include ResolvableDiscussion

  attr_reader :notes, :noteable

  delegate  :created_at,
            :project,
            :author,

            :noteable,
            :for_commit?,
            :for_merge_request?,

            to: :first_note

  def self.build(notes, noteable = nil)
    notes.first.discussion_class(noteable).new(notes, noteable)
  end

  def self.build_collection(notes, noteable = nil)
    notes.group_by { |n| n.discussion_id(noteable) }.values.map { |notes| build(notes, noteable) }
  end

  def self.discussion_id(note)
    Digest::SHA1.hexdigest(build_discussion_id(note).join("-"))
  end

  # Optionally override the discussion ID at runtime depending on circumstances
  def self.override_discussion_id(note)
    nil
  end

  def self.build_discussion_id_base(note)
    noteable_id = note.noteable_id || note.commit_id
    [:discussion, note.noteable_type.try(:underscore), noteable_id]
  end

  def self.build_discussion_id(note)
    [*build_discussion_id_base(note), SecureRandom.hex]
  end

  def initialize(notes, noteable = nil)
    @notes = notes
    @noteable = noteable
  end

  def ==(other)
    other.class == self.class &&
      other.noteable == self.noteable &&
      other.id == self.id &&
      other.notes == self.notes
  end

  def last_updated_at
    last_note.created_at
  end

  def last_updated_by
    last_note.author
  end

  def id
    first_note.discussion_id(noteable)
  end

  alias_method :to_param, :id

  def diff_discussion?
    false
  end

  def individual_note?
    false
  end

  def new_discussion?
    notes.length == 1
  end

  def last_note
    @last_note ||= notes.last
  end

  def collapsed?
    resolved?
  end

  def expanded?
    !collapsed?
  end

  def reply_attributes
    first_note.slice(:type, :noteable_type, :noteable_id, :commit_id, :discussion_id)
  end

  private

  def update
    # Do not select `Note.resolvable`, so that system notes remain in the collection
    notes_relation = Note.where(id: notes.map(&:id))

    yield(notes_relation)

    # Set the notes array to the updated notes
    @notes = notes_relation.fresh.to_a

    self.class.memoized_values.each do |var|
      instance_variable_set(:"@#{var}", nil)
    end
  end
end