diff --git a/app/models/tag.rb b/app/models/tag.rb index 825b90d8ad..6ff6afe609 100644 --- a/app/models/tag.rb +++ b/app/models/tag.rb @@ -5,15 +5,16 @@ class Tag < ActiveRecord::Base include HasDestroyedWebHook RESERVED_TAGS = [ - 'c' + 'c', + 'none' ] validates :name, presence: true, - uniqueness: { case_sensitive: false }, - exclusion: { in: RESERVED_TAGS } + uniqueness: { case_sensitive: false } validate :target_tag_validator, if: Proc.new { |t| t.new_record? || t.will_save_change_to_target_tag_id? } + validate :name_validator scope :where_name, ->(name) do name = Array(name).map(&:downcase) @@ -181,6 +182,14 @@ class Tag < ActiveRecord::Base true end end + + private + + def name_validator + if name.present? && RESERVED_TAGS.include?(self.name.strip.downcase) + errors.add(:name, :invalid) + end + end end # == Schema Information diff --git a/db/migrate/20200525072638_remove_none_tags.rb b/db/migrate/20200525072638_remove_none_tags.rb new file mode 100644 index 0000000000..ed50eea490 --- /dev/null +++ b/db/migrate/20200525072638_remove_none_tags.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class RemoveNoneTags < ActiveRecord::Migration[6.0] + def up + none_tag_id = DB.query_single("SELECT id FROM tags WHERE lower(name) = 'none'").first + if none_tag_id.present? + [:tag_users, :topic_tags, :category_tag_stats, :category_tags, :tag_group_memberships].each do |table_name| + execute "DELETE FROM #{table_name} WHERE tag_id = #{none_tag_id}" + end + execute "DELETE FROM tags WHERE id = #{none_tag_id} OR target_tag_id = #{none_tag_id}" + end + end + + def down + raise ActiveRecord::IrreversibleMigration + end +end diff --git a/spec/models/tag_spec.rb b/spec/models/tag_spec.rb index 441bb734ac..8bf0f7e7fe 100644 --- a/spec/models/tag_spec.rb +++ b/spec/models/tag_spec.rb @@ -36,6 +36,9 @@ describe Tag do expect { Fabricate.build(:tag, name: "hElLo").save! }.to raise_error(ActiveRecord::RecordInvalid) end + it 'does not allow creation of tag with name in "RESERVED_TAGS"' do + expect { Fabricate.build(:tag, name: "None").save! }.to raise_error(ActiveRecord::RecordInvalid) + end end describe 'destroy' do