For the sidebar content in MeinProf.de we use fragment caching. One problem with caching is that expiring entries can get really messy. Time-based caching can solve this problem but the current caching implementation in Rails does not support this.
While poking around in the MemCache-client implementation from the Robotcoop I saw that MemCache itself does support time-based expiry of cached entries. Thanks to Ruby I just re-implemented the write method in ActionController::Caching::Fragments::MemCacheStore so that we could expire our entries after some given time:
class ActionController::Caching::Fragments::MemCacheStore <br /> def write(name, value, options=nil) <br /> @data.set(name, value, 30.minutes) <br /> end <br />end
Now all fragments expire after 30 minutes. If you want to have different live-times for your caches you have to distinct by the name of the fragment. Normally fragments created with the <% cache do > call in views are named after the controller and action, e.g. controller/actionname. You can also specify a name like < cache(“UniPage_#{uni.id}”) do %>.
<blockquote>
class ActionController::Caching::Fragments::MemCacheStore
<br /> def write(name, value, options=nil)
<br /> if name =~ %r{^UniPage}
<br /> @data.set(name, value, 30.minutes)
<br /> elsif name == "mycontroller/myaction"
<br /> @data.set(name, value, 45.minutes)
<br /> else
<br /> @data.set(name, value, 60.minutes)
<br /> end
<br /> end
<br />end
Not the cleanest solution but it works very well for us.
If you want to also save your sessions in MemCache with the memcache-client library from the Robotcoop, add this code to ActionController::Caching::Fragments::MemCacheStore:
class ActionController::Caching::Fragments::MemCacheStore <br /> def data=(cache) <br /> @data = cache <br /> end <br />end
In summary our code in config/environments/production.rb looks like this:
### MemCached Server ###
<br />CACHE = MemCache.new :c_threshold => 10_000, :compression => true,\<br /> :debug => false, :namespace => 'meinprof_de', :readonly => false, :urlencode => false<br />
<br />CACHE.servers = '127.0.0.1:11211'
<br />
<br />### Sessions in MemCached ###
<br />session_options = {
<br /> :database_manager => CGI::Session::MemCacheStore,
<br /> :cache => CACHE
<br />}
<br />
<br />ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS.update session_options
<br />
<br />### FragmentCaching im MemCached ###
<br /># Allow us to set the CACHE as the Fragment Cache store
<br />class ActionController::Caching::Fragments::MemCacheStore
<br /> def data=(cache)
<br /> @data = cache
<br /> end
<br />
<br /> def write(name, value, options=nil)
<br /> if name =~ %r{^Random_TopFlop}
<br /> @data.set(name, value, 30.minutes)
<br /> elsif name =~ %r{^RegionPage}
<br /> @data.set(name, value, 60.minutes)
<br /> elsif name =~ %r{^UniPage}
<br /> @data.set(name, value, 60.minutes)
<br /> else
<br /> @data.set(name, value, 120.minutes)
<br /> end
<br /> end
<br />end<br />
<br />ActionController::Base.fragment_cache_store = :mem_cache_store ,{}
<br />ActionController::Base.fragment_cache_store.data = CACHE
