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
`----