1# frozen_string_literal: true 2 3module ResolvableNote 4 extend ActiveSupport::Concern 5 6 # Names of all subclasses of `Note` that can be resolvable. 7 RESOLVABLE_TYPES = %w(DiffNote DiscussionNote).freeze 8 9 included do 10 belongs_to :resolved_by, class_name: "User" 11 12 validates :resolved_by, presence: true, if: :resolved? 13 14 # Keep this scope in sync with `#potentially_resolvable?` 15 scope :potentially_resolvable, -> { where(type: RESOLVABLE_TYPES).where(noteable_type: Noteable.resolvable_types) } 16 # Keep this scope in sync with `#resolvable?` 17 scope :resolvable, -> { potentially_resolvable.user } 18 19 scope :resolved, -> { resolvable.where.not(resolved_at: nil) } 20 scope :unresolved, -> { resolvable.where(resolved_at: nil) } 21 end 22 23 class_methods do 24 # This method must be kept in sync with `#resolve!` 25 def resolve!(current_user) 26 unresolved.update_all(resolved_at: Time.current, resolved_by_id: current_user.id) 27 end 28 29 # This method must be kept in sync with `#unresolve!` 30 def unresolve! 31 resolved.update_all(resolved_at: nil, resolved_by_id: nil) 32 end 33 end 34 35 # Keep this method in sync with the `potentially_resolvable` scope 36 def potentially_resolvable? 37 RESOLVABLE_TYPES.include?(self.class.name) && noteable&.supports_resolvable_notes? 38 end 39 40 # Keep this method in sync with the `resolvable` scope 41 def resolvable? 42 potentially_resolvable? && !system? 43 end 44 45 def resolved? 46 return false unless resolvable? 47 48 self.resolved_at.present? 49 end 50 51 def to_be_resolved? 52 resolvable? && !resolved? 53 end 54 55 # If you update this method remember to also update `.resolve!` 56 def resolve_without_save(current_user, resolved_by_push: false) 57 return false unless resolvable? 58 return false if resolved? 59 60 self.resolved_at = Time.current 61 self.resolved_by = current_user 62 self.resolved_by_push = resolved_by_push 63 64 true 65 end 66 67 # If you update this method remember to also update `.unresolve!` 68 def unresolve_without_save 69 return false unless resolvable? 70 return false unless resolved? 71 72 self.resolved_at = nil 73 self.resolved_by = nil 74 75 true 76 end 77 78 def resolve!(current_user, resolved_by_push: false) 79 resolve_without_save(current_user, resolved_by_push: resolved_by_push) && 80 save! 81 end 82 83 def unresolve! 84 unresolve_without_save && save! 85 end 86end 87