# i use this method instead of "render"
render_from_cache_or_render(:cache_key =>â€cache keyâ€, :cache_expire_after => ConstantHelper::TAG_CLOUD_EXPIRED_IN, # minute
# implementation
def render_from_cache_or_render(p_args)
return render(p_args) if true == p_args[:cache_off]
# check from cache
cache_key = p_args[:cache_key]
cached_content = CacheService.get_cache(cache_key)
if not cached_content.nil? and not cached_content.empty?
return cached_content
else
content = render(p_args)
# cache expire time if defined
cache_expire_time_in_minutes = p_args[:cache_expire_after] || 60
CacheService.add_cache(cache_key, cache_expire_time_in_minutes, content)
return content
end
end
# complete source code of cache service
module Cache
class Item
attr_accessor :key, :expire_time, :content, :created_on
def initialize(p_key, p_expire_time, p_content)
@key = p_key
@expire_time = p_expire_time * 60 # in minutes
@content = p_content
@created_on = Time.now
end
end
end
class CacheService
@@CACHES = {}
@@CACHE_EXPIRE_TIMES = {}
def self.add_cache(p_key, p_expire_time, p_content)
cache_item = Cache::Item.new(p_key, p_expire_time, p_content)
@@CACHES[p_key.to_sym] = cache_item
end
def self.get_cache(p_key)
# load content from cache
cached_content = @@CACHES[p_key.to_sym]
return nil if cached_content.nil?
# verify cache validity
return cached_content.content if not expired?(cached_content)
return nil
end
private
def self.expired?(p_cache)
# find time difference
time_difference = Time.now - p_cache.created_on
return true if time_difference > p_cache.expire_time
end
end
Refactorings
No refactoring yet !
Jeremy Weiskotten
November 22, 2007, November 22, 2007 15:11, permalink
Just a refactoring of the expired? method.
def self.expired?(p_cache) p_cache.created_on < p_cache.expire_time.seconds.ago end
macournoyer
November 22, 2007, November 22, 2007 18:38, permalink
Why not used action caching ? http://api.rubyonrails.org/classes/ActionController/Caching/Actions.html
Or even better, page caching and play w/ the Expires header.
we4tech
November 23, 2007, November 23, 2007 05:01, permalink
hi @macournoyer,
thanks for your comment,
actually i didn't know about ActionController::Cache related option.
i was looking for some solution which has higher level abstraction and flexibility.
looking at the documentation, i think it is lacking some features which is more relevant with my project -
1. not event driven (which i will provide on my implementation)
2. couldn't find anyway to set cache expire time.
so far i found the follow good features -
1. supports multiple implementation
2. supports way to invalidate the fragment.
and again thanks for pointing action controller cache.
best wishes,
we4tech
November 23, 2007, November 23, 2007 05:04, permalink
hi @jeremy
i was trying to figure out what you did on your refactoring suggestion.
perhaps something is wrong, i couldn't find "seconds" method from "Time" class.
best wishes,
Jeremy Weiskotten
November 23, 2007, November 23, 2007 23:46, permalink
@we4tech: Rails' ActiveSupport module adds some methods to standard Ruby classes. A lot of it is really helpful -- you should familiarize yourself with it all.
This method was actually added to Ruby Numeric classes. See http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/Numeric/Time.html
Don't forget to rate my refactoring if you think it helps!
i was getting serious performance problem with one of my projects. so i came up with a simple fragment cache implementation on ruby on rails. i wrote another method which was used instead of "render" method.
as i had mongrel backed deployment, so i could get shared memory advantage. as you know mongrel under production mode it keeps only single instance of all models.