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.
I suggest using association callbacks.
class Part < ActiveRecord::Base
  has_many :sub_parts,
    :class_name => "Part",
    :after_add => :count_sub_parts,
    :after_remove => :count_sub_parts
  private
  def count_sub_parts
    update_attribute(:sub_part_count, calculate_sub_part_count)
  end
  def calculate_sub_part_count
    # perform the actual calculation here
  end
end
Nice and easy =)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With