Skip to content

Commit 35b68f4

Browse files
committed
Fix issue when reordering tags and @@remove_unused_tags is true
When reordering taggings, the taggings get deleted and recreated. However, by the time the taggings are recreated, the tags have already been removed. Fixed by wrapping the delete + create in a transaction, and only removing unused tags on transaction commit.
1 parent b1d7651 commit 35b68f4

4 files changed

Lines changed: 30 additions & 10 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ As such, _Breaking Changes_ are major. _Features_ would map to either major or m
1717
* Reduce packaged gem size
1818
* Fixes
1919
* [@iainbeeston Fix mismatched indentations warning message](https://github.com/mbleigh/acts-as-taggable-on/pull/1150)
20+
* [@james-reading Fix issue when reordering tags and @@remove_unused_tags is true](https://github.com/mbleigh/acts-as-taggable-on/pull/1154)
2021

2122
### [v12.0.0) / 2024-11-09](https://github.com/mbleigh/acts-as-taggable-on/compare/v11.0.0...v12.0.0)
2223

lib/acts-as-taggable-on/taggable/core.rb

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -272,15 +272,17 @@ def save_tags
272272
# Delete discarded tags and create new tags
273273
end
274274

275-
# Destroy old taggings:
276-
taggings.not_owned.by_context(context).where(tag_id: old_tags).destroy_all if old_tags.present?
277-
278-
# Create new taggings:
279-
new_tags.each do |tag|
280-
if taggable_tenant
281-
taggings.create!(tag_id: tag.id, context: context.to_s, taggable: self, tenant: taggable_tenant)
282-
else
283-
taggings.create!(tag_id: tag.id, context: context.to_s, taggable: self)
275+
transaction do
276+
# Destroy old taggings:
277+
taggings.not_owned.by_context(context).where(tag_id: old_tags).destroy_all if old_tags.present?
278+
279+
# Create new taggings:
280+
new_tags.each do |tag|
281+
if taggable_tenant
282+
taggings.create!(tag_id: tag.id, context: context.to_s, taggable: self, tenant: taggable_tenant)
283+
else
284+
taggings.create!(tag_id: tag.id, context: context.to_s, taggable: self)
285+
end
284286
end
285287
end
286288
end

lib/acts-as-taggable-on/tagging.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class Tagging < ActsAsTaggableOn.base_class.constantize # :nodoc:
2323

2424
validates_uniqueness_of :tag_id, scope: %i[taggable_type taggable_id context tagger_id tagger_type]
2525

26-
after_destroy :remove_unused_tags
26+
after_destroy_commit :remove_unused_tags
2727

2828
private
2929

spec/acts_as_taggable_on/taggable_spec.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,23 @@
9292
ids = @taggable.tags.map { |t| t.taggings.first.id }
9393
expect(ids).to eq(ids.sort)
9494
end
95+
96+
it 'can reorder tags successfully when @@remove_unused_tags is true' do
97+
previous_setting = ActsAsTaggableOn.remove_unused_tags
98+
ActsAsTaggableOn.remove_unused_tags = true
99+
100+
@taggable.tag_list = 'pow, ruby, rails'
101+
@taggable.save!
102+
@taggable.reload
103+
expect(@taggable.tag_list).to eq(%w(pow ruby rails))
104+
105+
@taggable.tag_list = 'rails, pow, ruby'
106+
@taggable.save!
107+
@taggable.reload
108+
expect(@taggable.tag_list).to eq(%w(rails pow ruby))
109+
ensure
110+
ActsAsTaggableOn.remove_unused_tags = previous_setting
111+
end
95112
end
96113

97114
RSpec.describe 'Taggable' do

0 commit comments

Comments
 (0)