cache pet images on items#show, in case that's what's being a super-slow jerkface

This commit is contained in:
Emi Matchu 2013-12-05 15:22:43 -06:00
parent cc7ac363dd
commit f07996d762
9 changed files with 88 additions and 61 deletions

View file

@ -2,7 +2,8 @@
var PREVIEW_SWF_ID = 'item-preview-swf',
PREVIEW_SWF = document.getElementById(PREVIEW_SWF_ID),
speciesList = $('#item-preview a'),
speciesEls,
petTypeEls,
customize_more_el = $('#customize-more'),
MainWardrobe;
@ -46,7 +47,7 @@ function PetType() {
this.setAsCurrent = function () {
PetType.current = this;
speciesList.filter('.current').removeClass('current');
petTypeEls.filter('.current').removeClass('current');
this.link.addClass('current');
customize_more_el.attr('href',
'http://impress.openneo.net/wardrobe?species=' + this.species_id +
@ -213,16 +214,40 @@ Preview.embed(PREVIEW_SWF_ID);
Item.createFromLocation().setAsCurrent();
Item.current.name = $('#item-name').text();
PetType.createFromLink(speciesList.eq(Math.floor(Math.random()*speciesList.length))).setAsCurrent();
// Choose only supported species, and remove the unsupported.
var supportedSpeciesIds = $('#item-preview-species').attr('data-supported-species-ids').split(',');
var supportedSpeciesIdPresenceMap = {};
for(var i = 0; i < supportedSpeciesIds.length; i++) {
supportedSpeciesIdPresenceMap[supportedSpeciesIds[i]] = true;
}
speciesEls = $('#item-preview-species > li').filter(function() {
var supported = supportedSpeciesIdPresenceMap[this.getAttribute('data-id')];
if(!supported) this.parentNode.removeChild(this);
return supported;
});
speciesList.each(function () {
// Choose random pet type for each species.
speciesEls.each(function() {
var speciesPetTypeEls = $(this).find('.pet-type');
var chosen = speciesPetTypeEls.eq(Math.floor(Math.random()*speciesPetTypeEls.length));
speciesPetTypeEls.not(chosen).remove();
});
petTypeEls = speciesEls.find('.pet-type');
// Choose random starting pet type
PetType.createFromLink(petTypeEls.eq(Math.floor(Math.random()*petTypeEls.length))).setAsCurrent();
// Setup pet type click behavior
petTypeEls.each(function () {
var el = $(this);
PetType.createFromLink(el);
}).live('click', function (e) {
e.preventDefault();
}).click(function (e) {
PetType.all[$(this).data('id')].setAsCurrent();
});
// Load the other pet type data in 5 seconds, to save database effort in case
// the user decides to bounce.
setTimeout($.proxy(Item.current, 'loadAllStandard'), 5000);
window.MainWardrobe = {View: {Outfit: {setFlashIsReady: previewSWFIsReady}}}

View file

@ -36,17 +36,18 @@ body.items-show
#item-preview
+clearfix
div
> div, > ul
float: left
#item-preview-species
display: block
width: 400px
a, img
.pet-type, img
height: 50px
width: 50px
a
.pet-type
+inline-block
&.current
background: $module-bg-color
@ -58,7 +59,10 @@ body.items-show
&.current
background: transparent
outline-color: $error_border_color
ul, li
display: inline
#item-preview-error
display: none
padding: 20px 10px 0

View file

@ -73,6 +73,11 @@ class ItemsController < ApplicationController
@contributors_with_counts = @item.contributors_with_counts
end
@supported_species_ids = @item.supported_species_ids
unless localized_fragment_exist?("items/show standard_species_images special_color=#{@item.special_color_id}")
@basic_colored_pet_types_by_species_id = PetType.special_color_or_basic(@item.special_color).includes_child_translations.group_by(&:species)
end
@trading_closet_hangers_by_owned = {
true => @item.closet_hangers.owned_trading.newest.includes(:user),
false => @item.closet_hangers.wanted_trading.newest.includes(:user)

View file

@ -27,31 +27,21 @@ module ItemsHelper
end
end
def standard_species_images_key_for(item)
versions_count = 1 # TODO
"foo" # TODO
end
def standard_species_images_for(item)
build_on_pet_types(item.supported_species, item.special_color) do |pet_type|
image = pet_type_image(pet_type, :happy, :face)
attributes = {
'data-id' => pet_type.id,
'data-body-id' => pet_type.body_id
}
[:color, :species].each do |pet_type_attribute_name|
pet_type_attribute = pet_type.send(pet_type_attribute_name)
[:id, :name].each do |subattribute_name|
attributes["data-#{pet_type_attribute_name}-#{subattribute_name}"] =
pet_type_attribute.send(subattribute_name)
end
end
link_to(
image,
'#',
attributes
)
end
def standard_species_images_for(pet_types_by_species_id)
pet_types_by_species_id.to_a.sort_by { |s, pt| s.name }.map { |species, pet_types|
pet_type_images = pet_types.map { |pet_type|
image = pet_type_image(pet_type, :happy, :face)
content_tag(:li, image, 'class' => 'pet-type',
'data-id' => pet_type.id,
'data-body-id' => pet_type.body_id,
'data-color-id' => pet_type.color.id,
'data-color-name' => pet_type.color.name,
'data-species-id' => pet_type.species.id,
'data-species-name' => pet_type.species.name)
}.join.html_safe
content_tag(:li, content_tag(:ul, pet_type_images),
'data-id' => species.id)
}.join.html_safe
end
def closet_list_verb(owned)

View file

@ -154,6 +154,10 @@ class Item < ActiveRecord::Base
@special_color ||= determine_special_color
end
def special_color_id
special_color.try(:id)
end
protected
def determine_special_color
I18n.with_locale(I18n.default_locale) do
@ -186,22 +190,18 @@ class Item < ActiveRecord::Base
replacement = replacement.join(',') if replacement.is_a?(Array)
write_attribute('species_support_ids', replacement)
end
def supported_species
def supported_species_ids
body_ids = swf_assets.select([:body_id]).map(&:body_id)
return Species.all if body_ids.include?(0)
return Species.select([:id]).map(&:id) if body_ids.include?(0)
pet_types = PetType.where(:body_id => body_ids).select('DISTINCT species_id')
species_ids = pet_types.map(&:species_id)
# If there are multiple known supported species, it probably supports them
# all. (I've never heard of only a handful of species being supported :P)
species_ids.size > 1 ? Species.all : Species.find(species_ids)
end
def supported_species_ids
supported_species.map(&:id)
species_ids.size >= 2 ? Species.select([:id]).map(&:id) : species_ids
end
def support_species?(species)

View file

@ -21,23 +21,16 @@ class PetType < ActiveRecord::Base
scope :includes_child_translations,
lambda { includes({:color => :translations, :species => :translations}) }
def self.standard_pet_types_by_species_id
# If we include Color.basic in the query, rather than getting the ID array
# first, it'll do this as a big fat JOIN unnecessarily. On production,
# there are tons of pet types and translations to send down, so tons of
# duplicate data is sent and must be merged together properly, both of
# which take serious time. So, this is a surprisingly significant
# performance boost - though I was surprised and impressed that Rails
# includes relations as subqueries. That's cool.
basic_color_ids = Color.basic.select([:id]).map(&:id)
PetType.where(color_id: basic_color_ids).includes_child_translations.
group_by(&:species_id)
def self.special_color_or_basic(special_color)
color_ids = special_color ? [special_color.id] : Color.basic.select([:id]).map(&:id)
where(color_id: color_ids)
end
def self.standard_body_ids
[].tap do |body_ids|
standard_pet_types_by_species_id.each do |species_id, pet_types|
# TODO: the nil hack is lame :P
special_color_or_basic(nil).group_by(&:species_id).each do |species_id, pet_types|
body_ids.concat(pet_types.map(&:body_id))
end
end
@ -45,7 +38,8 @@ class PetType < ActiveRecord::Base
def self.random_basic_per_species(species_ids)
random_pet_types = []
standards = self.standard_pet_types_by_species_id
# TODO: omg so lame :P
standards = special_color_or_basic(nil).group_by(&:species_id)
species_ids.each do |species_id|
pet_types = standards[species_id]
random_pet_types << pet_types[rand(pet_types.size)] if pet_types

View file

@ -0,0 +1,8 @@
class PetTypeObserver < ActiveRecord::Observer
include FragmentExpiration
def after_create(pet_type)
images_key = "items/show standard_species_images special_color=#{pet_type.color_id}"
expire_fragment_in_all_locales(images_key)
end
end

View file

@ -78,9 +78,10 @@
:class => 'button'
#item-preview
#item-preview-species
-# localized_cache random_standard_species_images_key do
= standard_species_images_for(@item)
%ul#item-preview-species{'data-supported-species-ids' => @supported_species_ids.join(',')}
-# TODO: filter by compatibility
- localized_cache "items/show standard_species_images special_color=#{@item.special_color_id}" do
= standard_species_images_for(@basic_colored_pet_types_by_species_id)
#item-preview-error
#item-preview-swf= t '.preview.requirements_not_met'

View file

@ -20,7 +20,7 @@ module OpenneoImpressItems
# config.plugins = [ :exception_notification, :ssl_requirement, :all ]
# Activate observers that should always be running
config.active_record.observers = :contribution_observer, :item_observer, :user_sweeper
config.active_record.observers = :contribution_observer, :item_observer, :pet_type_observer, :user_sweeper
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.