DEV: Enhance unique name finder to handle fallback name conflicts

This commit is contained in:
Gerhard Schlager
2025-11-03 11:14:17 +01:00
committed by Gerhard Schlager
parent 1150994e42
commit 6629e73449
5 changed files with 84 additions and 8 deletions
@@ -18,7 +18,7 @@ module Migrations::Importer
end
def find_available_name(name)
name, name_lower = find_available_name_internal(name)
name, name_lower = resolve_unique_name(name)
store_used_name(name_lower)
name
end
@@ -60,8 +60,8 @@ module Migrations::Importer
false
end
def find_available_name_internal(name)
name = sanitize_name(name)
def resolve_unique_name(original_name)
name = sanitize_name(original_name)
result =
if name.present?
@@ -141,13 +141,23 @@ module Migrations::Importer
def find_fallback_name
name = (@fallback_name ||= fallback_name)
name_lower = name.downcase
suffix = next_suffix(name_lower)
name_candidate = "#{name}_#{suffix}"
name_candidate_lower = name_candidate.downcase
attempts = 0
@last_suffixes[name_lower] = suffix
[name_candidate, name_candidate_lower]
while attempts < @max_attempts
name_candidate = "#{name}_#{suffix}"
name_candidate_lower = name_candidate.downcase
if name_available?(name_candidate_lower)
@last_suffixes[name_lower] = suffix
return name_candidate, name_candidate_lower
end
suffix += 1
attempts += 1
end
raise "Unable to find an available name after #{@max_attempts} attempts"
end
def next_suffix(name_lower)
@@ -129,5 +129,21 @@ RSpec.describe Migrations::Importer::BadgeNameFinder do
expect(name).to eq("Test & Badge!")
end
end
context "with fallback name conflicts" do
it "finds next available fallback name when some are already used" do
badge_rows << "badge_1"
badge_rows << "badge_123"
name1 = finder.find_available_name("")
119.times { finder.find_available_name("") }
name2 = finder.find_available_name("")
name3 = finder.find_available_name("")
expect(name1).to eq("Badge_2")
expect(name2).to eq("Badge_122")
expect(name3).to eq("Badge_124")
end
end
end
end
@@ -187,5 +187,21 @@ RSpec.describe Migrations::Importer::CategoryNameFinder do
expect(name).to eq("Test & Category!")
end
end
context "with fallback name conflicts" do
it "finds next available fallback name when some are already used" do
category_rows << [nil, "category_1"]
category_rows << [nil, "category_123"]
name1 = finder.find_available_name("", nil)
119.times { finder.find_available_name("", nil) }
name2 = finder.find_available_name("", nil)
name3 = finder.find_available_name("", nil)
expect(name1).to eq("Category_2")
expect(name2).to eq("Category_122")
expect(name3).to eq("Category_124")
end
end
end
end
@@ -231,5 +231,22 @@ RSpec.describe Migrations::Importer::GroupNameFinder do
expect(name).to eq("a_100")
end
end
context "with fallback name conflicts" do
it "finds next available fallback name when some are already used" do
fallback = I18n.t("importer.fallback_names.group")
group_names.add("#{fallback.downcase}_1")
group_names.add("#{fallback.downcase}_123")
name1 = finder.find_available_name("")
119.times { finder.find_available_name("") }
name2 = finder.find_available_name("")
name3 = finder.find_available_name("")
expect(name1).to eq("#{fallback}_2")
expect(name2).to eq("#{fallback}_122")
expect(name3).to eq("#{fallback}_124")
end
end
end
end
@@ -295,5 +295,22 @@ RSpec.describe Migrations::Importer::UsernameFinder do
expect(username).to eq("a_100")
end
end
context "with fallback name conflicts" do
it "finds next available fallback name when some are already used" do
fallback = I18n.t("importer.fallback_names.user")
usernames.add("#{fallback.downcase}_1")
usernames.add("#{fallback.downcase}_123")
username1 = finder.find_available_name("")
119.times { finder.find_available_name("") }
username2 = finder.find_available_name("")
username3 = finder.find_available_name("")
expect(username1).to eq("#{fallback}_2")
expect(username2).to eq("#{fallback}_122")
expect(username3).to eq("#{fallback}_124")
end
end
end
end