1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
# 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.
1 2 3
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.