Cache trade info on items#show, finally! I think it's the performance culprit.

This commit is contained in:
Emi Matchu 2013-12-27 14:49:46 -05:00
parent 5f95ef7e56
commit 6b340f906e
8 changed files with 102 additions and 24 deletions

View file

@ -51,6 +51,14 @@ class ClosetHanger < ActiveRecord::Base
}.to_json }.to_json
end end
def possibly_null_closet_list
list || user.null_closet_list(owned)
end
def trading?
possibly_null_closet_list.trading?
end
def verb(subject=:someone) def verb(subject=:someone)
self.class.verb(subject, owned?) self.class.verb(subject, owned?)
end end

View file

@ -1,7 +1,7 @@
class ClosetList < ActiveRecord::Base class ClosetList < ActiveRecord::Base
belongs_to :user belongs_to :user
has_many :hangers, :class_name => 'ClosetHanger', :foreign_key => 'list_id', has_many :hangers, :class_name => 'ClosetHanger', :foreign_key => 'list_id'
:dependent => :nullify # Nullification of associated records occurs in the ClosetListObserver.
attr_accessible :description, :hangers_owned, :name, :visibility attr_accessible :description, :hangers_owned, :name, :visibility
@ -27,5 +27,70 @@ class ClosetList < ActiveRecord::Base
end end
end end
end end
end
module VisibilityMethods
delegate :trading?, to: :visibility_level
def visibility_level
ClosetVisibility.levels[visibility]
end
def trading_changed?
return false unless visibility_changed?
level_change = visibility_change.map { |v| ClosetVisibility.levels[v] }
old_trading, new_trading = level_change.map(&:trading?)
old_trading != new_trading
end
end
include VisibilityMethods
class Null
include VisibilityMethods
attr_reader :user
def initialize(user)
@user = user
end
def hangers
user.closet_hangers.unlisted.where(owned: hangers_owned)
end
end
class NullOwned < Null
def hangers_owned
true
end
def visibility
user.owned_closet_hangers_visibility
end
def visibility_changed?
user.owned_closet_hangers_visibility_changed?
end
def visibility_change
user.owned_closet_hangers_visibility_change
end
end
class NullWanted < Null
def hangers_owned
false
end
def visibility
user.wanted_closet_hangers_visibility
end
def visibility_changed?
user.wanted_closet_hangers_visibility_changed?
end
def visibility_change
user.wanted_closet_hangers_visibility_change
end
end
end

View file

@ -16,6 +16,10 @@ module ClosetVisibility
def human_name def human_name
I18n.translate "closet_hangers.visibility.#{name}.name" I18n.translate "closet_hangers.visibility.#{name}.name"
end end
def trading?
id >= LEVELS_BY_NAME[:trading].id
end
end end
LEVELS = [ LEVELS = [

View file

@ -1,6 +1,4 @@
class ItemObserver < ActionController::Caching::Sweeper class ItemObserver < ActionController::Caching::Sweeper
include FragmentExpiration
def after_create(item) def after_create(item)
Resque.enqueue(Item::CreateTask, item.id) Resque.enqueue(Item::CreateTask, item.id)
end end

View file

@ -85,6 +85,10 @@ class User < ActiveRecord::Base
end end
end end
def null_closet_list(owned)
owned ? ClosetList::NullOwned.new(self) : ClosetList::NullWanted.new(self)
end
def self.find_or_create_from_remote_auth_data(user_data) def self.find_or_create_from_remote_auth_data(user_data)
user = find_or_initialize_by_remote_id_and_auth_server_id( user = find_or_initialize_by_remote_id_and_auth_server_id(
user_data['id'], user_data['id'],

View file

@ -1,13 +1,8 @@
class UserSweeper < ActionController::Caching::Sweeper class UserSweeper < ActionController::Caching::Sweeper
observe User observe User
def after_update(user)
def before_save(user) # Delegate null-list sweeping to the ClosetListObserver.
if user.points_changed? null_lists = [true, false].map { |owned| user.null_closet_list(owned) }
points_to_beat = User.points_required_to_pass_top_contributor(User::PreviewTopContributorsCount - 1) null_lists.each { |list| ClosetListObserver.instance.after_update(list) }
if user.points >= points_to_beat
expire_fragment(:controller => 'outfits', :action => 'new', :action_suffix => 'top_contributors')
end
end
true
end end
end end

View file

@ -61,15 +61,17 @@
- else - else
= list_zones @restricted_zones = list_zones @restricted_zones
#trade-hangers - localized_cache "items/#{@item.id} trade_hangers" do
- [true, false].each do |owned| #trade-hangers
%p - [true, false].each do |owned|
%strong - localized_cache "items/#{@item.id} trade_hangers owned=#{owned}" do
= trading_closet_hangers_header(owned, @trading_closet_hangers_by_owned[owned].size) %p
= render_trading_closet_hangers(owned) %strong
%span.toggle = trading_closet_hangers_header(owned, @trading_closet_hangers_by_owned[owned].size)
%span.more= t '.trading_closet_hangers.show_more' = render_trading_closet_hangers(owned)
%span.less= t '.trading_closet_hangers.show_less' %span.toggle
%span.more= t '.trading_closet_hangers.show_more'
%span.less= t '.trading_closet_hangers.show_less'
- localized_cache 'items#show preview_header' do - localized_cache 'items#show preview_header' do
#item-preview-header #item-preview-header

View file

@ -20,7 +20,9 @@ module OpenneoImpressItems
# config.plugins = [ :exception_notification, :ssl_requirement, :all ] # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
# Activate observers that should always be running # Activate observers that should always be running
config.active_record.observers = :contribution_observer, :item_observer, :pet_type_observer, :user_sweeper config.active_record.observers = [:closet_hanger_observer,
:closet_list_observer, :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. # 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. # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.