From 857cb547ed5c0b11d7265b35b51bf635b92ca056 Mon Sep 17 00:00:00 2001 From: Emi Matchu Date: Fri, 7 Jun 2024 20:10:06 -0700 Subject: [PATCH] Add `Item#dyeworks_base_item` database field, and populate it In this change, instead of *always* inferring the Dyeworks base item from the item name at runtime, we now have a database field that tracks it, and auto-populates whenever an item *seems* to need a Dyeworks base item but doesn't have one yet. This will enable us to set the base item manually in cases where it can't be inferred, and load Dyeworks base items for the Item Getting Guide in one query with `includes(:dyeworks_base_item)`. This migration does a bit more of the fix-em-up scripting work *in* the migration itself than I usually do, mainly because there's so much in this one that I think being extra-explicit is useful. We make sure to do it gracefully though! --- app/models/item.rb | 5 +- ...2149_add_dyeworks_base_item_id_to_items.rb | 91 +++++++++++++++++++ db/schema.rb | 5 +- 3 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 db/migrate/20240608022149_add_dyeworks_base_item_id_to_items.rb diff --git a/app/models/item.rb b/app/models/item.rb index 11cf774e..9650dc81 100644 --- a/app/models/item.rb +++ b/app/models/item.rb @@ -14,6 +14,9 @@ class Item < ApplicationRecord has_one :nc_mall_record has_many :parent_swf_asset_relationships, :as => :parent has_many :swf_assets, :through => :parent_swf_asset_relationships + belongs_to :dyeworks_base_item, class_name: "Item", + default: -> { inferred_dyeworks_base_item }, optional: true + attr_writer :current_body_id, :owned, :wanted @@ -208,7 +211,7 @@ class Item < ApplicationRecord Dyeworks\s+(?\S+)\s*(?.+) )$ }x - def dyeworks_base_item + def inferred_dyeworks_base_item name_match = name.match(DYEWORKS_NAME_PATTERN) return nil if name_match.nil? diff --git a/db/migrate/20240608022149_add_dyeworks_base_item_id_to_items.rb b/db/migrate/20240608022149_add_dyeworks_base_item_id_to_items.rb new file mode 100644 index 00000000..6f197f6e --- /dev/null +++ b/db/migrate/20240608022149_add_dyeworks_base_item_id_to_items.rb @@ -0,0 +1,91 @@ +class AddDyeworksBaseItemIdToItems < ActiveRecord::Migration[7.1] + def change + add_reference :items, :dyeworks_base_item, type: :integer, + foreign_key: {to_table: :items} + + # Find Dyeworks items, and fill in their base item field. (The Item model + # is configured to try to infer this when saving Dyeworks-seeming items + # with no matching base item yet.) + # + # Some item names that exist right now are known to not fit the pattern, so + # we try to set them manually if present in this copy of the database. + reversible do |direction| + direction.up do + dyeworks_items = Item.where("name LIKE ?", "Dyeworks %").to_a + + puts "Found #{dyeworks_items.size} Dyeworks items, " + + "inferring base items…" + dyeworks_items.each(&:save!) + + num_successes = dyeworks_items.select(&:dyeworks?).size + puts "Inferred Dyeworks base item for #{num_successes} items" + + set_manually "Baby Valentine Jumper and Shirt", + "Dyeworks Baby Blue: Baby Valentine Jumper", + "Dyeworks Baby Pink: Baby Valentine Jumper", + "Dyeworks Purple: Baby Valentine Jumper" + + set_manually "Field of Flowers Foreground", + "Dyeworks Black: Field of Flowers", + "Dyeworks Blue: Field of Flowers", + "Dyeworks Yellow: Field of Flowers" + + set_manually "2010 Games Master Challenge NC Challenge Lulu Shirt", + "Dyeworks Black: Games Master Challenge 2010 Lulu Shirt", + "Dyeworks Orange: Games Master Challenge 2010 Lulu Shirt", + "Dyeworks Purple: Games Master Challenge 2010 Lulu Shirt" + + set_manually "Stars and Glitter Face Paint", + "Dyeworks Blue: Stars and Glitter Facepaint", + "Dyeworks Green: Stars and Glitter Facepaint", + "Dyeworks Purple: Stars and Glitter Facepaint" + + set_manually "Hanging Winter Candle Garland", + "Dyeworks Brown: Hanging Winter Candles Garland", + "Dyeworks Purple: Hanging Winter Candles Garland", + "Dyeworks Silver: Hanging Winter Candles Garland" + + set_manually "Lovely Berry Blush Makeup", + "Dyeworks Magenta: Lovely Berry Blush", + "Dyeworks Peach: Lovely Berry Blush", + "Dyeworks Soft Pink: Lovely Berry Blush" + + set_manually "Winter Lights Effect", + "Dyeworks Orange & Pink: Winter Lights Effects", + "Dyeworks Red & Green: Winter Lights Effects", + "Dyeworks Yellow & Magenta: Winter Lights Effects" + + danglers = Item.where("name LIKE ?", "Dyeworks %"). + where(dyeworks_base_item_id: nil).to_a + puts "There are now #{danglers.size} Dyeworks-seeming items in the " + + "database without a matching base item." + danglers.each do |dangler| + puts "- #{dangler.name}" + end + end + end + end + + private + + def set_manually(base_item_name, *dyeworks_item_names) + base_item = Item.find_by_name(base_item_name) + if base_item.nil? + puts "Skipping all manual Dyeworks for base item #{base_item}: not found" + return + end + + dyeworks_item_names.each do |dyeworks_item_name| + dyeworks_item = Item.find_by_name(dyeworks_item_name) + if dyeworks_item.nil? + puts "Skipping manual Dyeworks for #{base_item_name} -> " + + "#{dyeworks_item_name}: not found" + next + end + + dyeworks_item.update!(dyeworks_base_item: base_item) + puts "Manually assigned Dyeworks #{base_item_name} -> " + + "#{dyeworks_item_name}" + end + end +end diff --git a/db/schema.rb b/db/schema.rb index c8b17787..f071ff9a 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2024_06_03_181855) do +ActiveRecord::Schema[7.1].define(version: 2024_06_08_022149) do create_table "alt_styles", charset: "utf8mb4", collation: "utf8mb4_unicode_520_ci", force: :cascade do |t| t.integer "species_id", null: false t.integer "color_id", null: false @@ -136,6 +136,8 @@ ActiveRecord::Schema[7.1].define(version: 2024_06_03_181855) do t.string "name", null: false t.text "description", size: :medium, null: false t.string "rarity", default: "", null: false + t.integer "dyeworks_base_item_id" + t.index ["dyeworks_base_item_id"], name: "index_items_on_dyeworks_base_item_id" t.index ["modeling_status_hint", "created_at", "id"], name: "items_modeling_status_hint_and_created_at_and_id" t.index ["modeling_status_hint", "created_at"], name: "items_modeling_status_hint_and_created_at" t.index ["modeling_status_hint", "id"], name: "items_modeling_status_hint_and_id" @@ -292,6 +294,7 @@ ActiveRecord::Schema[7.1].define(version: 2024_06_03_181855) do add_foreign_key "alt_styles", "colors" add_foreign_key "alt_styles", "species" + add_foreign_key "items", "items", column: "dyeworks_base_item_id" add_foreign_key "nc_mall_records", "items" add_foreign_key "outfits", "alt_styles" end