[英]How to store nil with Rails.cache.fetch & memcache?
我有一個現有的模型單例方法觸發我想要模型緩存的昂貴的數據庫查詢。 為此,我圍繞相關方法封裝了一個Rails.cache.fetch()
調用:
# app/models/specialist.rb
class Specialist < ActiveRecord::Base
def city
Rails.cache.fetch([self.class.name, self.id, "city"], expires_in: 23.hours) do
# expensive legacy query:
if responded?
o = offices.first
return nil if o.blank?
return o.city
elsif hospital_or_clinic_only?
(hospitals.map{ |h| h.city } + clinics.map{ |c| c.cities }).flatten.reject{ |i| i == nil }.uniq.first
elsif hospital_or_clinic_referrals_only?
(offices.map{ |o| o.city } + hospitals.map{ |h| h.city } + clinics.map{ |c| c.cities }).flatten.reject{ |c| c.blank? }.uniq.first
else
nil
end
end
end
end
對所有記錄執行.city
過去需要 16 秒; 使用這個Rails.cache.fetch
塊,它只下降到 7 秒,因為一半的記錄仍在觸發數據庫調用。
當我調查時,我發現當city
方法返回nil
,Rails.cache 不會將結果寫入 memcache——這意味着我的一半專家記錄仍然會觸發昂貴的數據庫查找,盡管被“緩存”
如何在使用 memcache 時強制Rails.cache.fetch
存儲nil
的值,以便不會觸發另一個數據庫查找以再次查找 nil?
一種解決方案是使用 NullObject,如下所示:
class Specialist
NullData = Struct.new(nil)
def city
result = Rails.cache.fetch([self.class.name, self.id, "city"], expires_in: 23.hours) do
if responded?
..
else
NullData.new()
end
result.is_a?(NullData) ? nil : result
end
end
這樣你就可以創建一個可以緩存的空對象。 然后當你返回時檢查它是否是一個已存儲的空對象,在這種情況下你返回 nil(以確保你不會破壞依賴於你的方法返回 nil 的舊代碼),否則你返回緩存的內容。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.