Adding custom cache field


#1

Hello,
I needed to add custom cache field for one of my application. I thought
I
will share the code showing how to do this.

This code below creates and maintain a custom cache field, for keeping
track
of totals. Say, you have accounts, and for each account there are
transactions
(either deposit/withdrawal), and one will like to keep track of the
total
balance for an account.

So, let there be a transactions table with the field ‘amount’ for which
we want
to keep track of the total. Then in the accounts table, we will need the
field, ‘transactions_total’.

And while declaring the models just add the line,

belongs_to_extra :accounts, :total_cache => :amount

This code below is tested with edge rail, and will work for polymorphic
associations also.

Any comments are welcome.

module ActiveRecord
module Associations # :nodoc:
def self.append_features(base)
super
base.extend(ClassMethods)
end

module ClassMethods

  def belongs_to_extra(association_id, options = { })
    association_type = association_id.to_s + "_type" if 

association_id
association_primary_key = association_id.to_s + “_id”
if options[:total_cache]
module_eval(
“after_create
'#{association_type}.constantize.modify_value(”#{self.to_s.underscore.pluralize

  • “_total”}",#{association_primary_key},#{options[:total_cache]})" +
    " unless #{association_type}.nil?’"
    )
    module_eval(
    “before_update
    '#{association_type}.constantize.modify_value(”#{self.to_s.underscore.pluralize

  • “_total”}",#{association_primary_key},#{options[:total_cache]} -
    #{self}.find(id).#{options[:total_cache]})" +
    " unless #{association_type}.nil?’")

        module_eval(
                    "before_destroy 
    

‘#{association_type}.constantize.modify_value("#{self.to_s.underscore.pluralize
+
“_total”}",#{association_primary_key}_type,-#{options[:total_cache]})"
+
" unless #{association_type}.nil?’"
)

    end
  end
end

class AssociationCollection
  def total
    count = if has_cached_total?
              @owner.send(:read_attribute,cached_total_attribute_name)
            end
  end
  def has_cached_total?
    @owner.attribute_present?(cached_total_attribute_name)
  end
  def cached_total_attribute_name
      "#{@reflection.name}_total"
  end
end

end
end

module ActiveRecord #:nodoc:
class Base
class << self # Class methods
def modify_value(total_name, id, value)
update_all “#{total_name} = #{total_name} + #{value}”,
“#{primary_key} = #{quote(id)}”
end
end
end
end


Surendra S.
http://ssinghi.kreeti.com, http://www.kreeti.com
Read my blog at: http://cuttingtheredtape.blogspot.com/
,----
| “All animals are equal, but some animals are more equal than others.”
| – Orwell, Animal Farm, 1945
`----