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!
This commit is contained in:
Emi Matchu 2024-09-05 17:52:35 -07:00
parent 176ab20fd1
commit edcb21558a
2 changed files with 13 additions and 7 deletions

View file

@ -555,10 +555,10 @@ class Item < ApplicationRecord
# Otherwise, create an appearance for each real (nonzero) body ID. We don't # 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, # 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? # 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_by_body_id.map do |body_id, body_specific_assets|
swf_assets_for_body = body_specific_assets + swf_assets_for_all_bodies 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_by_body_id[body_id])
body = Appearance::Body.new(body_id, species)
Appearance.new(self, body, swf_assets_for_body) Appearance.new(self, body, swf_assets_for_body)
end end
end end

View file

@ -3,11 +3,6 @@ class Species < ApplicationRecord
has_many :alt_styles has_many :alt_styles
scope :alphabetical, -> { order(:name) } 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={}) def as_json(options={})
super({only: [:id, :name], methods: [:human_name]}.merge(options)) super({only: [:id, :name], methods: [:human_name]}.merge(options))
@ -20,4 +15,15 @@ class Species < ApplicationRecord
I18n.translate('species.default_human_name') I18n.translate('species.default_human_name')
end end
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 end