I have a tree of active record objects, something like:
class Part < ActiveRecord::Base has_many :sub_parts, :class_name => 'Part' def complicated_calculation if sub_parts.size > 0 return self.sub_parts.inject(0){ |sum, current| sum + current.complicated_calculation } else sleep(1) return rand(10000) end end end
It is too costly to recalculate the complicated_calculation each time. So, I need a way to cache the value. However, if any part is changed, it needs to invalidate its cache and the cache of its parent, and grandparent, etc.
As a rough draft, I created a column to hold the cached calculation in the ‘parts’ table, but this smells a little rotten. It seems like there should be a cleaner way to cache the calculated values without stuffing them along side the ‘real’ columns.
You can stuff the actually cached values in the Rails cache (use memcached if you require that it be distributed).
The tough bit is cache expiry, but cache expiry is uncommon, right? In that case, we can just loop over each of the parent objects in turn and zap its cache, too. I added some ActiveRecord magic to your class to make getting the parent objects simplicity itself — and you don’t even need to touch your database. Remember to call
Part.sweep_complicated_cache(some_part)as appropriate in your code — you can put this in callbacks, etc, but I can’t add it for you because I don’t understand whencomplicated_calculationis changing.