Refactor Mentionable#notice_added_references
It now accounts for models that have changed but have already been persisted, such as when called from an UpdateService. Closes #1773
This commit is contained in:
parent
59d7f4c97f
commit
e4c698fd5c
|
@ -82,19 +82,33 @@ module Mentionable
|
|||
# If the mentionable_text field is about to change, locate any *added* references and create cross references for
|
||||
# them. Invoke from an observer's #before_save implementation.
|
||||
def notice_added_references(p = project, a = author)
|
||||
ch = changed_attributes
|
||||
original, mentionable_changed = "", false
|
||||
self.class.mentionable_attrs.each do |attr|
|
||||
if ch[attr]
|
||||
original << ch[attr]
|
||||
mentionable_changed = true
|
||||
end
|
||||
end
|
||||
changes = detect_mentionable_changes
|
||||
|
||||
# Only proceed if the saved changes actually include a chance to an attr_mentionable field.
|
||||
return unless mentionable_changed
|
||||
return if changes.empty?
|
||||
|
||||
preexisting = references(p, self.author, original)
|
||||
original_text = changes.collect { |_, vals| vals.first }.join(' ')
|
||||
|
||||
preexisting = references(p, self.author, original_text)
|
||||
create_cross_references!(p, a, preexisting)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Returns a Hash of changed mentionable fields
|
||||
#
|
||||
# Preference is given to the `changes` Hash, but falls back to
|
||||
# `previous_changes` if it's empty (i.e., the changes have already been
|
||||
# persisted).
|
||||
#
|
||||
# See ActiveModel::Dirty.
|
||||
#
|
||||
# Returns a Hash.
|
||||
def detect_mentionable_changes
|
||||
source = (changes.present? ? changes : previous_changes).dup
|
||||
|
||||
mentionable = self.class.mentionable_attrs
|
||||
|
||||
# Only include changed fields that are mentionable
|
||||
source.select { |key, val| mentionable.include?(key) }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -28,4 +28,53 @@ describe Issue, "Mentionable" do
|
|||
issue.create_cross_references!(project, author, [commit2])
|
||||
end
|
||||
end
|
||||
|
||||
describe '#notice_added_references' do
|
||||
let(:project) { create(:project) }
|
||||
let(:issues) { create_list(:issue, 2, project: project) }
|
||||
|
||||
context 'before changes are persisted' do
|
||||
it 'ignores pre-existing references' do
|
||||
issue = create_issue(description: issues[0].to_reference)
|
||||
|
||||
expect(SystemNoteService).not_to receive(:cross_reference)
|
||||
|
||||
issue.description = 'New description'
|
||||
issue.notice_added_references
|
||||
end
|
||||
|
||||
it 'notifies new references' do
|
||||
issue = create_issue(description: issues[0].to_reference)
|
||||
|
||||
expect(SystemNoteService).to receive(:cross_reference).with(issues[1], any_args)
|
||||
|
||||
issue.description = issues[1].to_reference
|
||||
issue.notice_added_references
|
||||
end
|
||||
end
|
||||
|
||||
context 'after changes are persisted' do
|
||||
it 'ignores pre-existing references' do
|
||||
issue = create_issue(description: issues[0].to_reference)
|
||||
|
||||
expect(SystemNoteService).not_to receive(:cross_reference)
|
||||
|
||||
issue.update_attributes(description: 'New description')
|
||||
issue.notice_added_references
|
||||
end
|
||||
|
||||
it 'notifies new references' do
|
||||
issue = create_issue(description: issues[0].to_reference)
|
||||
|
||||
expect(SystemNoteService).to receive(:cross_reference).with(issues[1], any_args)
|
||||
|
||||
issue.update_attributes(description: issues[1].to_reference)
|
||||
issue.notice_added_references
|
||||
end
|
||||
end
|
||||
|
||||
def create_issue(description:)
|
||||
create(:issue, project: project, description: description)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue