From edcb21558a42b91b70c4617d0c97e1d0ebaad3d9 Mon Sep 17 00:00:00 2001 From: Emi Matchu Date: Thu, 5 Sep 2024 17:52:35 -0700 Subject: [PATCH] Drastically reduce queries for item page preview Oh right okay, I made a sloppy perf hack long ago, and now let's actually clean it up! --- app/models/item.rb | 4 ++-- app/models/species.rb | 16 +++++++++++----- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/app/models/item.rb b/app/models/item.rb index 289251b5..9c81e70d 100644 --- a/app/models/item.rb +++ b/app/models/item.rb @@ -555,10 +555,10 @@ class Item < ApplicationRecord # Otherwise, create an appearance for each real (nonzero) body ID. We don't # generally expect body_id = 0 and body_id != 0 to mix, but if they do, # uhh, let's merge the body_id = 0 ones in? + species_by_body_id = Species.with_body_ids(swf_assets_by_body_id.keys) swf_assets_by_body_id.map do |body_id, body_specific_assets| swf_assets_for_body = body_specific_assets + swf_assets_for_all_bodies - species = Species.with_body_id(body_id).first! - body = Appearance::Body.new(body_id, species) + body = Appearance::Body.new(body_id, species_by_body_id[body_id]) Appearance.new(self, body, swf_assets_for_body) end end diff --git a/app/models/species.rb b/app/models/species.rb index f00d9905..9c5b1efe 100644 --- a/app/models/species.rb +++ b/app/models/species.rb @@ -3,11 +3,6 @@ class Species < ApplicationRecord has_many :alt_styles scope :alphabetical, -> { order(:name) } - - scope :with_body_id, -> body_id { - pt = PetType.arel_table - joins(:pet_types).where(pt[:body_id].eq(body_id)).limit(1) - } def as_json(options={}) super({only: [:id, :name], methods: [:human_name]}.merge(options)) @@ -20,4 +15,15 @@ class Species < ApplicationRecord I18n.translate('species.default_human_name') end end + + # Given a list of body IDs, return a hash from body ID to Species. + # (We assume that each body ID belongs to just one species; if not, which + # species we return for that body ID is undefined.) + def self.with_body_ids(body_ids) + species_ids_by_body_id = PetType.where(body_id: body_ids).distinct. + pluck(:body_id, :species_id).to_h + species_by_id = Species.where(id: species_ids_by_body_id.values). + to_h { |s| [s.id, s] } + species_ids_by_body_id.transform_values { |id| species_by_id[id] } + end end