I have a class in which looking up an instance is expensive, so instances are cached:
class Foo def self.find(id) Rails.cache.fetch('Foo.#{id}') do // some expensive lookup, like an HTTParty request, or a long SQL query ... end end end
That works fine until Foos have related Foos:
class Foo def children @child_foo_ids.map { |id| Foo.find(id) } end end
I’d like to use ||= caching to save repeated trips:
class Foo def children @children ||= @child_foo_ids.map { |id| Foo.find(id) } end end
But Rails.cache freezes the found Foos, so I can’t set the instance variable after I create and cache the object. (i.e. this method raises a TypeError.)
One solution would be to pre-fetch the parent when I first do the expensive find, but that could end up loading a gigantic object graph when I only want one or two instances.
You can use
||=caching; you just have to use a little indirection:Rails.cachewon’t freeze the instance variables of eachFoo, so thatHashcan be modified!PS: yes, I did just post this question and the answer at essentially the same time. I figured the community could benefit from my struggle.