diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d6867a6b..4ca031d5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ As such, _Breaking Changes_ are major. _Features_ would map to either major or m * Fixes * [@nbulaj Add support for Ruby 2.7 and it's kwargs](https://github.com/mbleigh/acts-as-taggable-on/pull/910) + * [@irphilli Tagging.remove_unused_tags should gracefully handle already deleted tags](https://github.com/mbleigh/acts-as-taggable-on/pull/988) ### [6.5.0 / 2019-11-07](https://github.com/mbleigh/acts-as-taggable-on/compare/v6.0.0...v6.5.0) diff --git a/lib/acts_as_taggable_on/tagging.rb b/lib/acts_as_taggable_on/tagging.rb index fc2ca90ca..ac2739ee7 100644 --- a/lib/acts_as_taggable_on/tagging.rb +++ b/lib/acts_as_taggable_on/tagging.rb @@ -24,13 +24,15 @@ class Tagging < ::ActiveRecord::Base #:nodoc: private def remove_unused_tags - if ActsAsTaggableOn.remove_unused_tags - if ActsAsTaggableOn.tags_counter - tag.destroy if tag.reload.taggings_count.zero? - else - tag.destroy if tag.reload.taggings.count.zero? - end + return if !ActsAsTaggableOn.remove_unused_tags || tag.blank? + + if ActsAsTaggableOn.tags_counter + tag.destroy if tag.reload.taggings_count.zero? + else + tag.destroy if tag.reload.taggings.count.zero? end + rescue ActiveRecord::RecordNotFound + # Tag already deleted - nothing else to do end end end diff --git a/spec/acts_as_taggable_on/tagging_spec.rb b/spec/acts_as_taggable_on/tagging_spec.rb index 7c3290a45..813ddff78 100644 --- a/spec/acts_as_taggable_on/tagging_spec.rb +++ b/spec/acts_as_taggable_on/tagging_spec.rb @@ -49,6 +49,26 @@ ActsAsTaggableOn.remove_unused_tags = previous_setting end + it 'should succesfully destroy taggings if tag already destroyed' do + previous_setting = ActsAsTaggableOn.remove_unused_tags + ActsAsTaggableOn.remove_unused_tags = true + ActsAsTaggableOn::Tag.destroy_all + expect(ActsAsTaggableOn::Tagging.count).to eql(0) + @taggable = TaggableModel.create(name: 'Bob Jones') + @taggable.update_attribute :tag_list, 'aaa,bbb,ccc' + + # Initalize taggings with preloaded tags + taggings = ActsAsTaggableOn::Tagging.preload(:tag).all + taggings.to_a + + # Delete tags before destroying taggings + ActsAsTaggableOn::Tag.delete_all + taggings.destroy_all + + expect(ActsAsTaggableOn::Tagging.count).to eql(0) + ActsAsTaggableOn.remove_unused_tags = previous_setting + end + describe 'context scopes' do before do @tagging_2 = ActsAsTaggableOn::Tagging.new