I have an existing Model singleton method triggering expensive database queries that I want to model cache. To do this, I wrapped a Rails.cache.fetch call around the method in question:
# apps/models/specialist.rb
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
Executing .city
on all records used to take 16 seconds; with this Rails.cache.fetch
block it only dropped to 7 seconds because half the records were still triggering database calls.
When I investigated I discovered that when the city
method returns nil
, Rails.cache does not write the result into memcache -- meaning half my specialist records still trigger expensive database lookups despite being "cached"
How do I force Rails.cache.fetch
to store the value of nil
when using memcache so that another database lookup to find nil again isn't triggered?
Aucun commentaire:
Enregistrer un commentaire