How can I put (parts of) a large object graph in Rails.cache?
I have a class where finding an instance is expensive, so the 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
This works fine until s are Foo
linked Foo
:
class Foo
def children
@child_foo_ids.map { |id| Foo.find(id) }
end
end
I would like to use caching ||=
to preserve repeated disconnections:
class Foo
def children
@children ||= @child_foo_ids.map { |id| Foo.find(id) }
end
end
But it Rails.cache
freezes the Foo
s found , so I can't set the instance variable after the object is created and cached. (i.e. this method calls a TypeError
.)
One solution is to prefetch parent
when I make a costly find first, but that can cause the gigantic graphic to load when I only need one or two instances.
source to share
You can use caching ||=
; you just need to touch a little:
class Foo
def initialize
@related_objects = {}
end
def children
@related_objects[:children] ||= @child_foo_ids.map { |id| Foo.find(id) }
end
end
Rails.cache
will not freeze instance variables for each Foo
, so that Hash
can be changed!
PS: yes, I just posed this question and answer at almost the same time. I figured the community could benefit from my struggle.
source to share