<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Blog.ubrious &#187; caching</title>
	<atom:link href="http://blog.ubrio.us/tag/caching/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.ubrio.us</link>
	<description>An Ordinary Web Developer's Blog</description>
	<lastBuildDate>Thu, 19 Jan 2012 00:44:59 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Simple rails time based fragment caching with file store</title>
		<link>http://blog.ubrio.us/ruby/ruby-rails/simple-rails-time-based-fragment-caching-with-file-store/</link>
		<comments>http://blog.ubrio.us/ruby/ruby-rails/simple-rails-time-based-fragment-caching-with-file-store/#comments</comments>
		<pubDate>Wed, 14 Jan 2009 11:27:41 +0000</pubDate>
		<dc:creator>Rob Hurring</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://blog.ubrio.us/?p=106</guid>
		<description><![CDATA[I spent a little while this morning looking around for a rails fragment caching solution which used a file store and had simple expirations built in. No luck. I could just use a memory based cache store, but for this particular problem it was too much overhead to setup and manage. 

The features are:

You can [...]]]></description>
			<content:encoded><![CDATA[<p>I spent a little while this morning looking around for a rails fragment caching solution which used a file store and had simple expirations built in. No luck. I could just use a memory based cache store, but for this particular problem it was too much overhead to setup and manage. </p>
<p><a name='features'></a></p>
<h3>The features are:</h3>
<ol>
<li>You can use it in the controller: <code>fragment_exist?(...)</code></li>
<li>You can use it in views: <code>cache(...) {}</code></li>
<li>Very lightweight</li>
<li>Behaves like the regular file store caching</li>
<li>Can expire caches automatically</li>
</ol>
<p><a name='code'></a></p>
<h3>Timed file store code</h3>
<pre class="brush: ruby;">
# lib/timed_file_store.rb
class TimedFileStore &lt; ActiveSupport::Cache::FileStore
  def exist?(name, options = {})
    delete_if_expired(name, options[:time_to_live]) unless options.blank? or options[:time_to_live].blank?
    super
  end
  def read(name, options = {})
    delete_if_expired(name, options[:time_to_live]) unless options.blank? or options[:time_to_live].blank?
    super
  end
protected
  def delete_if_expired(name, time_to_live = 0)
    delete(name) if expired?(name, time_to_live) rescue nil
  end
  def expired?(name, time_to_live = 0)
    return false unless time_to_live &gt; 0
    (Time.now - File.mtime(real_file_path(name))) &gt;= time_to_live
  end
end
</pre>
<p><a name='usage'></a></p>
<h3>Setup &amp; Usage</h3>
<pre class="brush: ruby;">
# environment.rb
# same as :file_store -- just add timed_
config.cache_store = :timed_file_store, File.join(RAILS_ROOT, 'tmp', 'cache')
</pre>
<p><strong>Time based expiration from the controller</strong></p>
<p>Having the controller control the expiration of the cache is good if you are passing along any objects to the views since it will not re-run the code if it is already cached. I&#8217;m using this for a long running report currently.</p>
<pre class="brush: ruby;">
# YourController.rb
# don't run the report if we are cached
@report = Report.find(params[:id])
unless fragment_exists?(&quot;report_#{@report.id}&quot;, :time_to_live =&gt; 1.week)
  @report.run!
end

# views/reports/show.html.erb -- or whatever view file
&lt;% cache(&quot;report_#{@report.id}&quot;) do -%&gt;
  &lt;!-- output the report HTML and such --&gt;
&lt;% end -%&gt;
</pre>
<p>This will expire the fragment and re-run the report after the cache&#8217;s File.mtime is older than a week. The view doesn&#8217;t have anything to do with it so it acts like the normal FileStore.</p>
<p><strong>Time based expiration in the view</strong></p>
<p>If you aren&#8217;t running any intense code in the controller and just want to keep a certain view fragment cached for a while, this should work. (** I didn&#8217;t test this since I only needed the previous method, but it should work &#8212; maybe with some slight tweaks? <img src='http://blog.ubrio.us/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<pre class="brush: ruby;">
# views/wherever/whatever.html.erb
&lt;% cache(&quot;whatever&quot;, :time_to_live =&gt; 1.hour) do -%&gt;
  &lt;!-- This is my HTML content and all that jazz --&gt;
  &lt;!-- After 1 hour this cache should be re-freshed --&gt;
&lt;% end -%&gt;
</pre>
<p>Not sure how useful that would be when considering action and page caching&#8230; but its possible. The only thing I noticed is that in the log when the cache deletes itself it shows a &#8220;Cached fragment hit:&#8221; then a &#8220;Cached fragment miss:&#8221; &#8212; probably needs some attention if I ever get around to it.</p>
<p>Let me know if this works out, and/or any issues, bugs, etc.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ubrio.us/ruby/ruby-rails/simple-rails-time-based-fragment-caching-with-file-store/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

