Hi, I''ve made a model cache for rails, to use when you want to cache
model instance methods, rather than controller calls. Does anything
similar exist already? Any comments on the implementation?
Since it serializes cached data, it might be good to add the following
to environment.rb to get YAML-support for the rails class autoloading
mechanism.
-- add to environment.rb
# YAML support for class autoloading
YAML.add_domain_type("ActiveRecord,2007", "") do |type, val|
klass = type.split('':'').last.constantize
YAML.object_maker(klass, val)
end
class ActiveRecord::Base
def to_yaml_type
"!ActiveRecord,2007/#{self.class}"
end
def to_yaml_properties # only store the attributes
[''@attributes'']
end
end
-- model_cache_helper.rb
# ModelCache to use on an ActiveRecord class to cache method calls.
Example:
#
# Class X < ActiveRecord::Base
# def heavy_calculation(a, b)
# "result #{self.x} #{a} #{b}"
# end
#
# include ModelCacheHelper
# cache_method :heavy_calculation
# end
#
# The created method X.heavy_calculation(id, arg1, arg2) will then
check if the
# result is cached, otherwise it will do
X.find(1).heavy_calculation(arg1, arg2)
# and cache the result. Calling heavy_calculation on an instance of X
will also
# cache the result.
#
# The instance method expire_cache, will expire the cache for that
object. It
# can be used with an optional argument, expire_cache(method), to only
expire
# the cache for a certain method.
#
# Non-string result will be serialized with YAML and automatically
deserialized
# when loaded.
module ModelCacheHelper
def self.included(klass)
klass.extend ClassMethods
end
module ClassMethods
def check_cache(url, args)
c = ActionController::Base.new
return yield unless c.perform_caching
url += args.map do |a|
[String,Fixnum,Symbol,TrueClass,FalseClass].member?(a.class) ?
a.to_s : nil
end.join("-")
unless f = c.read_fragment(url)
res = yield
c.write_fragment(url, res.is_a?(String) ? res : res.to_yaml)
res
else
(f[0..3] == "--- ") ? YAML.load(f) : f
end
end
def cache_method(method)
controller = self.class_name.underscore.pluralize
self.class_eval %Q{
def self.#{method}(id, *args)
check_cache("#{controller}/\#{id}-#{method}-", args) do
self.find(id).#{method}_without_cache(*args)
end
end
def #{method}_with_cache(*args)
self.class.check_cache("#{controller}/\#{id}-#{method}-",
args) do
#{method}_without_cache(*args)
end
end
alias_method_chain :#{method}, :cache
}
end
end
def expire_cache(method = false)
c = ActionController::Base.new
return unless c.perform_caching
controller = self.class.class_name.underscore.pluralize
puts "expire #{controller} - id #{self.id}"
unless method
c.expire_fragment %r{#{controller}/#{self.id}-.*}
else
c.expire_fragment %r{#{controller}/#{self.id}-#{method}-.*}
end
end
end
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---