https://github.com/JackDanger/cached_values/
Cache the result of any Ruby expression or SQL into an ActiveRecord attribute. Expire and update automatically.
- as gem: sudo gem install cached_values
- as plugin: ./script/plugin install git://github.com/JackDanger/cached_values.git
You can calculate values with a single line in any ActiveRecord model. To actually save those values you'll need to create an attribute in your schema. By default the cached_value instance will look for an attribute with the same name as itself. You can override this by specifying a :cache => :some_attribute option
A very simple case in which cached_values works just like the .count method on a has_many association:
class Leprechaun < ActiveRecord::Base
caches_value :total_gold_coins, :sql => 'select count(*) from gold_coins where leprechaun_id = #{id}'
end
Company.find(4).total_employees # => 45
A more sophisticated example:
class Leprechaun < ActiveRecord::Base
has_many :lucky_charms
has_many :deceived_children, :through => :lucky_charms
caches_value :total_children_remaining_to_be_deceived, :sql => '... very complicated sql here ...'
end
Leprechaun.find(14).total_children_remaining_to_be_deceived # => 6,692,243,122
The values can be of any type. The plugin will attempt to cast SQL results to the type corresponding with their database cache but calculations in Ruby are left alone.
You can also calculate the value in Ruby using a string to be eval'ed or a Proc. Both are evaluated in the context of the record instance.
class Leprechaun < ActiveRecord::Base
caches_value :total_gold, :eval => "some_archaic_and_silly_calculation(gold_coins)"
caches_value :total_lucky_charms, :eval => Proc.new {|record| record.calculate_total_lucky_charms }
end
The cache is customizable, you can specify which attribute should be used as a cache:
caches_value :runic_formula, :sql => '...' # uses 'runic_formula' column if it exists
caches_value :standard_deviation_of_gold_over_time, # uses 'std' column if it exists
:sql => '...', :cache => 'std'
caches_value :id, :sql => '...', :cache => false # does NOT persist to db, just memoize in memory. This avoids overwriting the attribute of the same name.
ActiveRecord callbacks can be used to reload (update cache and reload instance) at certain times:
caches_value :standard_deviation, :sql => '...', :reload => [:before_save, :after_destroy]
caches_value :runic_formula, :sql => '...', :reload => :after_create
Patches welcome, forks celebrated.
Copyright (c) 2007 Jack Danger Canty @ http://jåck.com, released under the MIT license