split weapon_series data migration into three separate files

This commit is contained in:
Justin Edmund 2025-12-03 12:56:51 -08:00
parent f64fd63b6c
commit 83d065e2f9
4 changed files with 245 additions and 128 deletions

View file

@ -0,0 +1,77 @@
# frozen_string_literal: true
class CreateWeaponSeriesRecords < ActiveRecord::Migration[8.0]
def up
# Canonical weapon series data matching the frontend JSON exactly
weapon_series_data = [
{ order: 0, slug: 'gacha', name_en: 'Gacha Weapons', name_jp: 'ガチャ武器' },
{ order: 1, slug: 'seraphic', name_en: 'Seraphic Weapons', name_jp: 'セラフィックウェポン' },
{ order: 2, slug: 'grand', name_en: 'Grand Weapons', name_jp: 'リミテッドシリーズ' },
{ order: 3, slug: 'dark-opus', name_en: 'Dark Opus Weapons', name_jp: '終末の神器', has_weapon_keys: true },
{ order: 4, slug: 'destroyer', name_en: 'Destroyer Weapons', name_jp: '破壊の標', extra: true, has_weapon_keys: true },
{ order: 5, slug: 'draconic', name_en: 'Draconic Weapons', name_jp: 'ドラコニックウェポン・オリジン', has_weapon_keys: true },
{ order: 6, slug: 'draconic-providence', name_en: 'Draconic Weapons Providence', name_jp: 'ドラコニックウェポン', extra: true, has_weapon_keys: true },
{ order: 7, slug: 'new-world-foundation', name_en: 'New World Foundation', name_jp: '新世界の礎', extra: true },
{ order: 8, slug: 'astral', name_en: 'Astral Weapons', name_jp: 'アストラルウェポン' },
{ order: 9, slug: 'ultima', name_en: 'Ultima Weapons', name_jp: 'オメガウェポン', element_changeable: true, has_weapon_keys: true },
{ order: 10, slug: 'bahamut', name_en: 'Bahamut Weapons', name_jp: 'バハムートウェポン', extra: true },
{ order: 11, slug: 'cosmos', name_en: 'Cosmos Weapons', name_jp: 'コスモスシリーズ' },
{ order: 12, slug: 'hollowsky', name_en: 'Hollowsky Weapons', name_jp: '虚ろなる神器' },
{ order: 13, slug: 'omega', name_en: 'Omega Weapons', name_jp: 'マグナシリーズ' },
{ order: 14, slug: 'regalia', name_en: 'Regalia Weapons', name_jp: 'レガリアシリーズ' },
{ order: 15, slug: 'omega-rebirth', name_en: 'Omega Rebirth Weapons', name_jp: 'マグナ・リバースシリーズ' },
{ order: 16, slug: 'malice', name_en: 'Malice Weapons', name_jp: 'マリスシリーズ' },
{ order: 17, slug: 'menace', name_en: 'Menace Weapons', name_jp: 'メネスシリーズ' },
{ order: 18, slug: 'ennead', name_en: 'Ennead Weapons', name_jp: 'エニアドシリーズ' },
{ order: 19, slug: 'ancestral', name_en: 'Ancestral Weapons', name_jp: 'アンセスタルシリーズ' },
{ order: 20, slug: 'revans', name_en: 'Revans Weapons', name_jp: 'レヴァンスウェポン', has_awakening: true },
{ order: 21, slug: 'revenant', name_en: 'Revenant Weapons', name_jp: '天星器', element_changeable: true },
{ order: 22, slug: 'celestial', name_en: 'Celestial Weapons', name_jp: '極星器', extra: true, has_awakening: true },
{ order: 23, slug: 'xeno', name_en: 'Xeno Weapons', name_jp: '六道武器' },
{ order: 24, slug: 'exo', name_en: 'Exo Weapons', name_jp: 'エクスウェポン', has_awakening: true },
{ order: 25, slug: 'beast', name_en: 'Beast Weapons', name_jp: '四象武器' },
{ order: 26, slug: 'proven', name_en: 'Proven Weapons', name_jp: 'ブレイブウェポン', has_awakening: true },
{ order: 27, slug: 'superlative', name_en: 'Superlative Weapons', name_jp: 'スペリオシリーズ', element_changeable: true },
{ order: 28, slug: 'illustrious', name_en: 'Illustrious Weapons', name_jp: 'ルミナスシリーズ' },
{ order: 29, slug: 'vintage', name_en: 'Vintage Weapons', name_jp: 'ヴィンテージシリーズ' },
{ order: 30, slug: 'class-champion', name_en: 'Class Champion Weapons', name_jp: '英雄武器', element_changeable: true, has_weapon_keys: true },
{ order: 31, slug: 'rose', name_en: 'Rose Weapons', name_jp: 'ローズシリーズ' },
{ order: 32, slug: 'primal', name_en: 'Primal Weapons', name_jp: 'プライマルシリーズ' },
{ order: 33, slug: 'olden-primal', name_en: 'Olden Primal Weapons', name_jp: 'オールド・プライマルシリーズ' },
{ order: 34, slug: 'epic', name_en: 'Epic Weapons', name_jp: 'エピックウェポン' },
{ order: 35, slug: 'militis', name_en: 'Militis Weapons', name_jp: 'ミーレスシリーズ', extra: true },
{ order: 36, slug: 'sephira', name_en: 'Sephira Weapons', name_jp: 'セフィラン・オールドウェポン', extra: true },
{ order: 37, slug: 'world', name_en: 'World Weapons', name_jp: 'ワールドシリーズ', extra: true, has_awakening: true },
{ order: 38, slug: 'replica', name_en: 'Replicas', name_jp: '複製品' },
{ order: 39, slug: 'rusted', name_en: 'Rusted Weapons', name_jp: '朽ち果てた武器' },
{ order: 40, slug: 'relic', name_en: 'Relics', name_jp: '依代' },
{ order: 41, slug: 'eternal-splendor', name_en: 'Weapons of Eternal Splendor', name_jp: '十天光輝' },
{ order: 42, slug: 'vyrmament', name_en: 'Vyrmament', name_jp: 'オイラは' },
{ order: 43, slug: 'collab', name_en: 'Collab', name_jp: 'コラボ武器' },
{ order: 44, slug: 'event', name_en: 'Event', name_jp: 'イベント武器' }
]
puts "Creating weapon series records..."
weapon_series_data.each do |data|
ws = WeaponSeries.find_or_initialize_by(slug: data[:slug])
ws.assign_attributes(
name_en: data[:name_en],
name_jp: data[:name_jp],
order: data[:order],
extra: data[:extra] || false,
element_changeable: data[:element_changeable] || false,
has_weapon_keys: data[:has_weapon_keys] || false,
has_awakening: data[:has_awakening] || false,
has_ax_skills: data[:has_ax_skills] || false
)
ws.save!
puts " #{ws.slug}: #{ws.name_en}"
end
puts "\nCreated #{WeaponSeries.count} weapon series records"
end
def down
WeaponSeries.delete_all
end
end

View file

@ -1,128 +0,0 @@
# frozen_string_literal: true
class PopulateWeaponSeriesAndMigrate < ActiveRecord::Migration[8.0]
def up
# Canonical weapon series data matching the frontend JSON exactly
# legacy_id maps to the current Weapon.series integer column (from SERIES_SLUGS)
weapon_series_data = [
{ legacy_id: 99, order: 0, slug: 'gacha', name_en: 'Gacha Weapons', name_jp: 'ガチャ武器' },
{ legacy_id: 1, order: 1, slug: 'seraphic', name_en: 'Seraphic Weapons', name_jp: 'セラフィックウェポン' },
{ legacy_id: 2, order: 2, slug: 'grand', name_en: 'Grand Weapons', name_jp: 'リミテッドシリーズ' },
{ legacy_id: 3, order: 3, slug: 'dark-opus', name_en: 'Dark Opus Weapons', name_jp: '終末の神器', has_weapon_keys: true },
{ legacy_id: nil, order: 4, slug: 'destroyer', name_en: 'Destroyer Weapons', name_jp: '破壊の標', extra: true, has_weapon_keys: true },
{ legacy_id: 27, order: 5, slug: 'draconic', name_en: 'Draconic Weapons', name_jp: 'ドラコニックウェポン・オリジン', has_weapon_keys: true },
{ legacy_id: 40, order: 6, slug: 'draconic-providence', name_en: 'Draconic Weapons Providence', name_jp: 'ドラコニックウェポン', extra: true, has_weapon_keys: true },
{ legacy_id: 30, order: 7, slug: 'new-world-foundation', name_en: 'New World Foundation', name_jp: '新世界の礎', extra: true },
{ legacy_id: 26, order: 8, slug: 'astral', name_en: 'Astral Weapons', name_jp: 'アストラルウェポン' },
{ legacy_id: 13, order: 9, slug: 'ultima', name_en: 'Ultima Weapons', name_jp: 'オメガウェポン', element_changeable: true, has_weapon_keys: true },
{ legacy_id: 14, order: 10, slug: 'bahamut', name_en: 'Bahamut Weapons', name_jp: 'バハムートウェポン', extra: true },
{ legacy_id: 16, order: 11, slug: 'cosmos', name_en: 'Cosmos Weapons', name_jp: 'コスモスシリーズ' },
{ legacy_id: 10, order: 12, slug: 'hollowsky', name_en: 'Hollowsky Weapons', name_jp: '虚ろなる神器' },
{ legacy_id: 8, order: 13, slug: 'omega', name_en: 'Omega Weapons', name_jp: 'マグナシリーズ' },
{ legacy_id: 7, order: 14, slug: 'regalia', name_en: 'Regalia Weapons', name_jp: 'レガリアシリーズ' },
{ legacy_id: 42, order: 15, slug: 'omega-rebirth', name_en: 'Omega Rebirth Weapons', name_jp: 'マグナ・リバースシリーズ' },
{ legacy_id: 33, order: 16, slug: 'malice', name_en: 'Malice Weapons', name_jp: 'マリスシリーズ' },
{ legacy_id: 34, order: 17, slug: 'menace', name_en: 'Menace Weapons', name_jp: 'メネスシリーズ' },
{ legacy_id: 31, order: 18, slug: 'ennead', name_en: 'Ennead Weapons', name_jp: 'エニアドシリーズ' },
{ legacy_id: 29, order: 19, slug: 'ancestral', name_en: 'Ancestral Weapons', name_jp: 'アンセスタルシリーズ' },
{ legacy_id: 37, order: 20, slug: 'revans', name_en: 'Revans Weapons', name_jp: 'レヴァンスウェポン', has_awakening: true },
{ legacy_id: 4, order: 21, slug: 'revenant', name_en: 'Revenant Weapons', name_jp: '天星器', element_changeable: true },
{ legacy_id: 41, order: 22, slug: 'celestial', name_en: 'Celestial Weapons', name_jp: '極星器', extra: true, has_awakening: true },
{ legacy_id: 11, order: 23, slug: 'xeno', name_en: 'Xeno Weapons', name_jp: '六道武器' },
{ legacy_id: 39, order: 24, slug: 'exo', name_en: 'Exo Weapons', name_jp: 'エクスウェポン', has_awakening: true },
{ legacy_id: 6, order: 25, slug: 'beast', name_en: 'Beast Weapons', name_jp: '四象武器' },
{ legacy_id: 36, order: 26, slug: 'proven', name_en: 'Proven Weapons', name_jp: 'ブレイブウェポン', has_awakening: true },
{ legacy_id: 17, order: 27, slug: 'superlative', name_en: 'Superlative Weapons', name_jp: 'スペリオシリーズ', element_changeable: true },
{ legacy_id: 35, order: 28, slug: 'illustrious', name_en: 'Illustrious Weapons', name_jp: 'ルミナスシリーズ' },
{ legacy_id: 18, order: 29, slug: 'vintage', name_en: 'Vintage Weapons', name_jp: 'ヴィンテージシリーズ' },
{ legacy_id: 19, order: 30, slug: 'class-champion', name_en: 'Class Champion Weapons', name_jp: '英雄武器', element_changeable: true, has_weapon_keys: true },
{ legacy_id: 12, order: 31, slug: 'rose', name_en: 'Rose Weapons', name_jp: 'ローズシリーズ' },
{ legacy_id: 5, order: 32, slug: 'primal', name_en: 'Primal Weapons', name_jp: 'プライマルシリーズ' },
{ legacy_id: 9, order: 33, slug: 'olden-primal', name_en: 'Olden Primal Weapons', name_jp: 'オールド・プライマルシリーズ' },
{ legacy_id: 15, order: 34, slug: 'epic', name_en: 'Epic Weapons', name_jp: 'エピックウェポン' },
{ legacy_id: 32, order: 35, slug: 'militis', name_en: 'Militis Weapons', name_jp: 'ミーレスシリーズ', extra: true },
{ legacy_id: 23, order: 36, slug: 'sephira', name_en: 'Sephira Weapons', name_jp: 'セフィラン・オールドウェポン', extra: true },
{ legacy_id: 38, order: 37, slug: 'world', name_en: 'World Weapons', name_jp: 'ワールドシリーズ', extra: true, has_awakening: true },
{ legacy_id: 20, order: 38, slug: 'replica', name_en: 'Replicas', name_jp: '複製品' },
{ legacy_id: 22, order: 39, slug: 'rusted', name_en: 'Rusted Weapons', name_jp: '朽ち果てた武器' },
{ legacy_id: 21, order: 40, slug: 'relic', name_en: 'Relics', name_jp: '依代' },
{ legacy_id: 28, order: 41, slug: 'eternal-splendor', name_en: 'Weapons of Eternal Splendor', name_jp: '十天光輝' },
{ legacy_id: 24, order: 42, slug: 'vyrmament', name_en: 'Vyrmament', name_jp: 'オイラは' },
{ legacy_id: 43, order: 43, slug: 'collab', name_en: 'Collab', name_jp: 'コラボ武器' },
{ legacy_id: 98, order: 44, slug: 'event', name_en: 'Event', name_jp: 'イベント武器' }
]
# Build mapping from legacy series integer to new weapon_series_id
legacy_to_uuid = {}
puts "Creating/updating weapon series records..."
weapon_series_data.each do |data|
ws = WeaponSeries.find_or_initialize_by(slug: data[:slug])
ws.assign_attributes(
name_en: data[:name_en],
name_jp: data[:name_jp],
order: data[:order],
extra: data[:extra] || false,
element_changeable: data[:element_changeable] || false,
has_weapon_keys: data[:has_weapon_keys] || false,
has_awakening: data[:has_awakening] || false,
has_ax_skills: data[:has_ax_skills] || false
)
ws.save!
legacy_to_uuid[data[:legacy_id]] = ws.id if data[:legacy_id].present?
puts " #{ws.slug}: #{ws.name_en}"
end
puts "\nMigrating weapons to use weapon_series_id..."
migrated = 0
skipped = 0
Weapon.find_each do |weapon|
next if weapon.series.blank?
weapon_series_id = legacy_to_uuid[weapon.series.to_i]
if weapon_series_id
weapon.update_column(:weapon_series_id, weapon_series_id)
migrated += 1
else
puts " Warning: No weapon_series found for legacy series #{weapon.series} (weapon: #{weapon.name_en})"
skipped += 1
end
end
puts " Migrated #{migrated} weapons, skipped #{skipped}"
puts "\nMigrating weapon_key series to weapon_key_series join table..."
key_count = 0
WeaponKey.find_each do |weapon_key|
next if weapon_key.series.blank?
weapon_key.series.each do |legacy_series_id|
weapon_series_id = legacy_to_uuid[legacy_series_id.to_i]
next unless weapon_series_id
# Create join record if it doesn't exist
WeaponKeySeries.find_or_create_by!(
weapon_key_id: weapon_key.id,
weapon_series_id: weapon_series_id
)
key_count += 1
end
end
puts " Created #{key_count} weapon_key_series associations"
puts "\nWeapon series migration complete!"
end
def down
# Remove all weapon_key_series records
WeaponKeySeries.delete_all
# Clear weapon_series_id from all weapons
Weapon.update_all(weapon_series_id: nil)
# Delete all weapon_series records
WeaponSeries.delete_all
end
end

View file

@ -0,0 +1,83 @@
# frozen_string_literal: true
class MigrateWeaponKeySeries < ActiveRecord::Migration[8.0]
# Mapping from legacy series integer (WeaponKey.series array values) to WeaponSeries slug
LEGACY_TO_SLUG = {
1 => 'seraphic',
2 => 'grand',
3 => 'dark-opus',
4 => 'revenant',
5 => 'primal',
6 => 'beast',
7 => 'regalia',
8 => 'omega',
9 => 'olden-primal',
10 => 'hollowsky',
11 => 'xeno',
12 => 'rose',
13 => 'ultima',
14 => 'bahamut',
15 => 'epic',
16 => 'cosmos',
17 => 'superlative',
18 => 'vintage',
19 => 'class-champion',
20 => 'replica',
21 => 'relic',
22 => 'rusted',
23 => 'sephira',
24 => 'vyrmament',
26 => 'astral',
27 => 'draconic',
28 => 'eternal-splendor',
29 => 'ancestral',
30 => 'new-world-foundation',
31 => 'ennead',
32 => 'militis',
33 => 'malice',
34 => 'menace',
35 => 'illustrious',
36 => 'proven',
37 => 'revans',
38 => 'world',
39 => 'exo',
40 => 'draconic-providence',
41 => 'celestial',
42 => 'omega-rebirth',
43 => 'collab',
98 => 'event',
99 => 'gacha'
}.freeze
def up
# Build lookup from slug to UUID
slug_to_uuid = WeaponSeries.pluck(:slug, :id).to_h
puts "Migrating weapon_key series to weapon_key_series join table..."
key_count = 0
WeaponKey.find_each do |weapon_key|
next if weapon_key.series.blank?
weapon_key.series.each do |legacy_series_id|
slug = LEGACY_TO_SLUG[legacy_series_id.to_i]
next unless slug
weapon_series_id = slug_to_uuid[slug]
next unless weapon_series_id
WeaponKeySeries.find_or_create_by!(
weapon_key_id: weapon_key.id,
weapon_series_id: weapon_series_id
)
key_count += 1
end
end
puts " Created #{key_count} weapon_key_series associations"
end
def down
WeaponKeySeries.delete_all
end
end

View file

@ -0,0 +1,85 @@
# frozen_string_literal: true
class MigrateWeaponsToWeaponSeries < ActiveRecord::Migration[8.0]
# Mapping from legacy series integer (Weapon.series column) to WeaponSeries slug
LEGACY_TO_SLUG = {
0 => 'seraphic',
1 => 'grand',
2 => 'dark-opus',
4 => 'revenant',
6 => 'primal',
5 => 'beast',
7 => 'beast',
9 => 'omega',
8 => 'regalia',
10 => 'primal',
12 => 'hollowsky',
13 => 'xeno',
15 => 'rose',
17 => 'ultima',
16 => 'bahamut',
18 => 'epic',
20 => 'cosmos',
22 => 'superlative',
23 => 'vintage',
24 => 'class-champion',
28 => 'sephira',
14 => 'astral',
3 => 'draconic',
21 => 'ancestral',
29 => 'new-world-foundation',
19 => 'ennead',
11 => 'militis',
26 => 'malice',
27 => 'menace',
31 => 'illustrious',
25 => 'proven',
30 => 'revans',
32 => 'world',
33 => 'exo',
34 => 'draconic-providence',
37 => 'celestial',
41 => 'celestial',
38 => 'omega-rebirth',
43 => 'collab',
35 => 'event',
-1 => 'gacha',
36 => 'gacha'
}.freeze
def up
# Build lookup from slug to UUID
slug_to_uuid = WeaponSeries.pluck(:slug, :id).to_h
puts 'Migrating weapons to use weapon_series_id...'
migrated = 0
skipped = 0
Weapon.find_each do |weapon|
next if weapon.series.blank?
slug = LEGACY_TO_SLUG[weapon.series.to_i]
unless slug
puts " Warning: No slug mapping for legacy series #{weapon.series} (weapon: #{weapon.name_en})"
skipped += 1
next
end
weapon_series_id = slug_to_uuid[slug]
unless weapon_series_id
puts " Warning: No weapon_series found for slug '#{slug}' (weapon: #{weapon.name_en})"
skipped += 1
next
end
weapon.update_column(:weapon_series_id, weapon_series_id)
migrated += 1
end
puts " Migrated #{migrated} weapons, skipped #{skipped}"
end
def down
Weapon.update_all(weapon_series_id: nil)
end
end