From 1ce32e5867f1803ce15dbdda1dfda216fee52461 Mon Sep 17 00:00:00 2001 From: Matchu Date: Fri, 27 Dec 2013 21:11:03 -0500 Subject: [PATCH] Use item proxies better for items#index?format=html :D We used get_multi when preparing the proxies to decide which to load from the database, but then sent multiple get requests to Memcache to re-fetch the same data from that get_multi. Silly! Use the data that's already stored on the proxy anyway. --- app/helpers/items_helper.rb | 9 ++++++++- app/models/item/proxy.rb | 15 ++++++++++++--- app/models/item/proxy_array.rb | 4 ++-- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/app/helpers/items_helper.rb b/app/helpers/items_helper.rb index bee6f618..b3afb191 100644 --- a/app/helpers/items_helper.rb +++ b/app/helpers/items_helper.rb @@ -126,7 +126,14 @@ module ItemsHelper # helper, we have to do some indirection. Fake that the render is in a # template, then capture the resulting buffer output. capture do - localized_cache("items/#{item.id}#item_link_partial") do + # Try to read from the prepared proxy's known partial output, if it's + # even a proxy at all. + if item.respond_to?(:known_partial_output) + prepared_output = item.known_partial_output(:item_link_partial).html_safe + else + prepared_output = nil + end + prepared_output || localized_cache("items/#{item.id}#item_link_partial") do safe_concat render(partial: 'items/item_link', locals: {item: item}) end end diff --git a/app/models/item/proxy.rb b/app/models/item/proxy.rb index 20b16178..18e2eafe 100644 --- a/app/models/item/proxy.rb +++ b/app/models/item/proxy.rb @@ -11,8 +11,13 @@ class Item Item.model_name end - def initialize(id) - @id = id + def initialize(item_or_id) + if item_or_id.is_a? Item + @item = item_or_id + @id = @item.id + else + @id = item_or_id.to_i + end @known_outputs = {method: {}, partial: {}} end @@ -46,12 +51,16 @@ class Item @known_outputs[type][name] = value end + def known_partial_output(name) + @known_outputs[:partial][name] + end + private def cache_method(method_name, *args, &block) # Two layers of cache: a local copy, in case the method is called again, # and then the Rails cache, before we hit the actual method call. - @known_outputs[method_name] ||= begin + @known_outputs[:method][method_name] ||= begin key = fragment_key(:method, method_name) Rails.cache.fetch(key) { item.send(method_name, *args) } end diff --git a/app/models/item/proxy_array.rb b/app/models/item/proxy_array.rb index f1174736..d8c5a714 100644 --- a/app/models/item/proxy_array.rb +++ b/app/models/item/proxy_array.rb @@ -12,8 +12,8 @@ class Item } }) - def initialize(ids) - self.replace(ids.map { |id| Proxy.new(id.to_i) }) + def initialize(items_or_ids) + self.replace(items_or_ids.map { |item_or_id| Proxy.new(item_or_id) }) end def prepare_method(name)