Alex Rivera | Logout

How can I cache a calculated column in rails?

Asked 2008-10-08T01:39:11.543
16

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.

Edit
Report

2 Answers

2

Have a field similar to a counter cache. For example: order_items_amount and have that be a cached calculated field.

Use a after_save filter to recalculate the field on anything that can modify that value. (Including the record itself)

Edit: This is basically what you have now. I don't know of any cleaner solution unless you wanted to store cached calculated fields in another table.

answered 2008-10-08T01:42:40.037
1

I've found that sometimes there is good reason to de-normalize information in your database. I have something similar in an app that I am working on and I just re-calculate that field anytime the collection changes.

It doesn't use a cache and it stores the most up to date figure in the database.

answered 2008-10-13T16:57:22.640

Your Answer