20fdbbe86a
Goldiloader (https://github.com/salsify/goldiloader) can eager load associations automatically. This removes the need for adding "includes" calls in a variety of different places. This also comes with the added benefit of not having to eager load data if it's not used.
111 lines
2.7 KiB
Ruby
111 lines
2.7 KiB
Ruby
module ResolvableDiscussion
|
|
extend ActiveSupport::Concern
|
|
include ::Gitlab::Utils::StrongMemoize
|
|
|
|
included do
|
|
# A number of properties of this `Discussion`, like `first_note` and `resolvable?`, are memoized.
|
|
# When this discussion is resolved or unresolved, the values of these properties potentially change.
|
|
# To make sure all memoized values are reset when this happens, `update` resets all instance variables with names in
|
|
# `memoized_variables`. If you add a memoized method in `ResolvableDiscussion` or any `Discussion` subclass,
|
|
# please make sure the instance variable name is added to `memoized_values`, like below.
|
|
cattr_accessor :memoized_values, instance_accessor: false do
|
|
[]
|
|
end
|
|
|
|
memoized_values.push(
|
|
:resolvable,
|
|
:resolved,
|
|
:first_note,
|
|
:first_note_to_resolve,
|
|
:last_resolved_note,
|
|
:last_note
|
|
)
|
|
|
|
delegate :potentially_resolvable?, to: :first_note
|
|
|
|
delegate :resolved_at,
|
|
:resolved_by,
|
|
:resolved_by_push?,
|
|
|
|
to: :last_resolved_note,
|
|
allow_nil: true
|
|
end
|
|
|
|
def resolvable?
|
|
strong_memoize(:resolvable) do
|
|
potentially_resolvable? && notes.any?(&:resolvable?)
|
|
end
|
|
end
|
|
|
|
def resolved?
|
|
strong_memoize(:resolved) do
|
|
resolvable? && notes.none?(&:to_be_resolved?)
|
|
end
|
|
end
|
|
|
|
def first_note
|
|
strong_memoize(:first_note) do
|
|
notes.first
|
|
end
|
|
end
|
|
|
|
def first_note_to_resolve
|
|
return unless resolvable?
|
|
|
|
strong_memoize(:first_note_to_resolve) do
|
|
notes.find(&:to_be_resolved?)
|
|
end
|
|
end
|
|
|
|
def last_resolved_note
|
|
return unless resolved?
|
|
|
|
strong_memoize(:last_resolved_note) do
|
|
resolved_notes.sort_by(&:resolved_at).last
|
|
end
|
|
end
|
|
|
|
def resolved_notes
|
|
notes.select(&:resolved?)
|
|
end
|
|
|
|
def to_be_resolved?
|
|
resolvable? && !resolved?
|
|
end
|
|
|
|
def can_resolve?(current_user)
|
|
return false unless current_user
|
|
return false unless resolvable?
|
|
|
|
current_user == self.noteable.author ||
|
|
current_user.can?(:resolve_note, self.project)
|
|
end
|
|
|
|
def resolve!(current_user)
|
|
return unless resolvable?
|
|
|
|
update { |notes| notes.resolve!(current_user) }
|
|
end
|
|
|
|
def unresolve!
|
|
return unless resolvable?
|
|
|
|
update { |notes| notes.unresolve! }
|
|
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.auto_include(false).to_a # rubocop:disable Gitlab/ModuleWithInstanceVariables
|
|
|
|
self.class.memoized_values.each do |name|
|
|
clear_memoization(name)
|
|
end
|
|
end
|
|
end
|