Class: Discussion
Overview
A non-diff discussion on an issue, merge request, commit, or snippet, consisting of ‘DiscussionNote` notes.
A discussion of this type can be resolvable.
Constant Summary
collapse
- CACHE_VERSION =
Bump this if we need to refresh the cached versions of discussions
1
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
#can_resolve?, #clear_memoized_values, #first_note, #first_note_to_resolve, #last_resolved_note, #resolvable?, #resolve!, #resolved?, #resolved_by_push?, #resolved_notes, #to_be_resolved?, #unresolve!
Constructor Details
#initialize(notes, context_noteable = nil, inverse_relations: true) ⇒ Discussion
111
112
113
114
115
116
|
# File 'app/models/discussion.rb', line 111
def initialize(notes, context_noteable = nil, inverse_relations: true)
@notes = notes
@context_noteable = context_noteable
notes.each { |n| n.discussion = self } if inverse_relations
end
|
Instance Attribute Details
#context_noteable ⇒ Object
Returns the value of attribute context_noteable.
13
14
15
|
# File 'app/models/discussion.rb', line 13
def context_noteable
@context_noteable
end
|
#notes ⇒ Object
Returns the value of attribute notes.
14
15
16
|
# File 'app/models/discussion.rb', line 14
def notes
@notes
end
|
Class Method Details
.base_discussion_id(note) ⇒ Object
81
82
83
84
|
# File 'app/models/discussion.rb', line 81
def self.base_discussion_id(note)
noteable_id = note.noteable_id || note.commit_id
[:discussion, note.noteable_type.try(:underscore), noteable_id]
end
|
.build(notes, context_noteable = nil, inverse_relations: true) ⇒ Object
43
44
45
|
# File 'app/models/discussion.rb', line 43
def self.build(notes, context_noteable = nil, inverse_relations: true)
notes.first.discussion_class(context_noteable).new(notes, context_noteable, inverse_relations: inverse_relations)
end
|
.build_collection(notes, context_noteable = nil) ⇒ Object
47
48
49
50
|
# File 'app/models/discussion.rb', line 47
def self.build_collection(notes, context_noteable = nil)
grouped_notes = notes.group_by { |n| n.discussion_id(context_noteable) }
grouped_notes.values.map { |notes| build(notes, context_noteable) }
end
|
.build_discussion_id(note) ⇒ Object
Returns an array of discussion ID components
77
78
79
|
# File 'app/models/discussion.rb', line 77
def self.build_discussion_id(note)
[*base_discussion_id(note), SecureRandom.hex]
end
|
.build_discussions(discussion_ids, context_noteable = nil, preload_note_diff_file: false) ⇒ Object
52
53
54
55
56
57
58
|
# File 'app/models/discussion.rb', line 52
def self.build_discussions(discussion_ids, context_noteable = nil, preload_note_diff_file: false)
notes = model_class.where(discussion_id: discussion_ids).fresh
notes = notes.inc_note_diff_file if preload_note_diff_file
grouped_notes = notes.group_by(&:discussion_id)
grouped_notes.transform_values { |notes| Discussion.build(notes, context_noteable) }
end
|
.discussion_id(note) ⇒ Object
Returns an alphanumeric discussion ID based on ‘build_discussion_id`
72
73
74
|
# File 'app/models/discussion.rb', line 72
def self.discussion_id(note)
Digest::SHA1.hexdigest(build_discussion_id(note).join("-"))
end
|
.lazy_find(discussion_id) ⇒ Object
60
61
62
63
64
65
66
67
68
69
|
# File 'app/models/discussion.rb', line 60
def self.lazy_find(discussion_id)
BatchLoader.for(discussion_id).batch do |discussion_ids, loader|
results = model_class.where(discussion_id: discussion_ids).fresh.to_a.group_by(&:discussion_id)
results.each do |discussion_id, notes|
next if notes.empty?
loader.call(discussion_id, Discussion.build(notes))
end
end
end
|
.model_class ⇒ Object
107
108
109
|
# File 'app/models/discussion.rb', line 107
def self.model_class
Note
end
|
.note_class ⇒ Object
103
104
105
|
# File 'app/models/discussion.rb', line 103
def self.note_class
DiscussionNote
end
|
.override_discussion_id(note) ⇒ Object
When notes on a commit are displayed in context of a merge request that contains that commit, these notes are to be displayed as if they were part of one discussion, even though they were actually individual notes on the commit with different discussion IDs, so that it’s clear that these are not notes on the merge request itself.
To turn a list of notes into a list of discussions, they are grouped by discussion ID, so to get these out-of-context notes to end up in the same discussion, we need to get them to return the same ‘discussion_id` when this grouping happens. To enable this, `Note#discussion_id` calls out to the `override_discussion_id` method on the appropriate `Discussion` subclass, as determined by the `discussion_class` method on `Note` or a subclass of `Note`.
If no override is necessary, return ‘nil`. For the case described above, see `OutOfContextDiscussion.override_discussion_id`.
99
100
101
|
# File 'app/models/discussion.rb', line 99
def self.override_discussion_id(note)
nil
end
|
Instance Method Details
#==(other) ⇒ Object
122
123
124
125
126
127
|
# File 'app/models/discussion.rb', line 122
def ==(other)
other.class == self.class &&
other.context_noteable == self.context_noteable &&
other.id == self.id &&
other.notes == self.notes
end
|
#cache_key ⇒ Object
181
182
183
184
185
186
187
188
189
190
191
192
193
|
# File 'app/models/discussion.rb', line 181
def cache_key
notes_sha = Digest::SHA1.hexdigest(notes.map(&:post_processed_cache_key).join(':'))
[
CACHE_VERSION,
id,
notes_sha,
resolved_at
].join(':')
end
|
#can_convert_to_discussion? ⇒ Boolean
161
162
163
|
# File 'app/models/discussion.rb', line 161
def can_convert_to_discussion?
false
end
|
#can_resolve_discussion?(user) ⇒ Boolean
210
211
212
|
# File 'app/models/discussion.rb', line 210
def can_resolve_discussion?(user)
!first_note.system? && user&.can?(:resolve_note, first_note)
end
|
#collapsed? ⇒ Boolean
169
170
171
|
# File 'app/models/discussion.rb', line 169
def collapsed?
resolved?
end
|
#declarative_policy_delegate ⇒ Object
35
36
37
|
# File 'app/models/discussion.rb', line 35
def declarative_policy_delegate
first_note
end
|
#diff_discussion? ⇒ Boolean
153
154
155
|
# File 'app/models/discussion.rb', line 153
def diff_discussion?
false
end
|
#discussion_class ⇒ Object
202
203
204
|
# File 'app/models/discussion.rb', line 202
def discussion_class
::Discussion
end
|
#expanded? ⇒ Boolean
173
174
175
|
# File 'app/models/discussion.rb', line 173
def expanded?
!collapsed?
end
|
#id ⇒ Object
Also known as:
to_param
141
142
143
|
# File 'app/models/discussion.rb', line 141
def id
first_note.discussion_id(context_noteable)
end
|
#individual_note? ⇒ Boolean
157
158
159
|
# File 'app/models/discussion.rb', line 157
def individual_note?
false
end
|
#last_note ⇒ Object
165
166
167
|
# File 'app/models/discussion.rb', line 165
def last_note
@last_note ||= notes.last
end
|
#last_updated_at ⇒ Object
129
130
131
|
# File 'app/models/discussion.rb', line 129
def last_updated_at
last_note.created_at
end
|
#last_updated_by ⇒ Object
133
134
135
|
# File 'app/models/discussion.rb', line 133
def last_updated_by
last_note.author
end
|
#noteable_collection_name ⇒ Object
206
207
208
|
# File 'app/models/discussion.rb', line 206
def noteable_collection_name
noteable.class.underscore.pluralize
end
|
#on_image? ⇒ Boolean
118
119
120
|
# File 'app/models/discussion.rb', line 118
def on_image?
false
end
|
#project_id ⇒ Object
39
40
41
|
# File 'app/models/discussion.rb', line 39
def project_id
project&.id
end
|
#reply_attributes ⇒ Object
177
178
179
|
# File 'app/models/discussion.rb', line 177
def reply_attributes
first_note.slice(:type, :noteable_type, :noteable_id, :commit_id, :discussion_id)
end
|
#reply_id ⇒ Object
145
146
147
148
149
|
# File 'app/models/discussion.rb', line 145
def reply_id
first_note.discussion_id
end
|
#to_global_id(options = {}) ⇒ Object
Consolidate discussions GID. There is no need to have different GID for different class names as the discussion_id hash is already unique per discussion. This also fixes the issue where same discussion may return different GIDs depending on number of notes it has.
198
199
200
|
# File 'app/models/discussion.rb', line 198
def to_global_id(options = {})
GlobalID.new(::Gitlab::GlobalId.build(model_name: discussion_class.to_s, id: id))
end
|
#updated? ⇒ Boolean
137
138
139
|
# File 'app/models/discussion.rb', line 137
def updated?
last_updated_at != created_at
end
|