<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">

  <title>Inject is for Wizards</title>
  
  <link href="http://injectisforwizards.com/" />
  <updated>2011-10-12T20:16:44+11:00</updated>
  <id>http://injectisforwizards.com/</id>
  <author>
    <name>Gareth Townsend</name>
    
  </author>

  
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/inject-is-for-wizards" /><feedburner:info uri="inject-is-for-wizards" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
    <title>Read Through Caching of ActiveResource</title>
    <link href="http://feedproxy.google.com/~r/inject-is-for-wizards/~3/saJX4OwYCXI/" />
    <updated>2011-09-21T19:57:00+10:00</updated>
    <id>http://injectisforwizards.com/blog/read-through-caching-of-activeresource</id>
    <content type="html">&lt;p&gt;&lt;a href="http://api.rubyonrails.org/classes/ActiveResource/Base.html"&gt;ActiveResource&lt;/a&gt; makes talking to REST API's easy.
The beauty of ActiveResource objects is that they mimic ActiveRecord objects, providing a familiar interface to rails developers.&lt;/p&gt;

&lt;p&gt;The problem is that a REST API is not a database connection.
There's quite a bit going on to create your objects. ActiveResource sends an API request, your API handles that, gets the records from the database, marshals it into json, sends it over the network, ActiveResource un-marshals the data, and finally returns a ruby object.&lt;/p&gt;

&lt;p&gt;If you have a page with many ActiveResource objects being displayed on it, you can kiss any hopes of scalability and performance goodbye.&lt;/p&gt;

&lt;p&gt;So it makes sense that you would try and limit the number of times you request the same information from an API.
Ideally you would take advantage of cache-control max-age headers, last-modified headers and ETags to limit the number of redundant API requests.
ActiveResource doesn't respect any of these caching strategies, and adding support for them turns out to be a non-trivial task.
Believe me, I tried.&lt;/p&gt;

&lt;p&gt;Thankfully there is a simple solution, implement a read through cache.&lt;/p&gt;

&lt;h3&gt;What is a Read Through Cache?&lt;/h3&gt;

&lt;p&gt;A read through cache is quite simple, it's designed to serve data from a cache if it has it, otherwise to fetch it from the source.&lt;/p&gt;

&lt;p&gt;The algorithm is as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Attempt to read from the cache.&lt;/li&gt;
&lt;li&gt;If no results are found, read from the original source.&lt;/li&gt;
&lt;li&gt;Write the results to the cache.&lt;/li&gt;
&lt;li&gt;Return the results.&lt;/li&gt;
&lt;/ol&gt;


&lt;h3&gt;An Implementation&lt;/h3&gt;

&lt;p&gt;In order to add read through caching to ActiveResource, we need to build a module that can hook into the ActiveResource find class methods:&lt;/p&gt;

&lt;div&gt;&lt;figure role=code&gt; &lt;div class="highlight"&gt;&lt;table cellpadding="0" cellspacing="0"&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;span class='line'&gt;5&lt;/span&gt;
&lt;span class='line'&gt;6&lt;/span&gt;
&lt;span class='line'&gt;7&lt;/span&gt;
&lt;span class='line'&gt;8&lt;/span&gt;
&lt;span class='line'&gt;9&lt;/span&gt;
&lt;span class='line'&gt;10&lt;/span&gt;
&lt;span class='line'&gt;11&lt;/span&gt;
&lt;span class='line'&gt;12&lt;/span&gt;
&lt;span class='line'&gt;13&lt;/span&gt;
&lt;span class='line'&gt;14&lt;/span&gt;
&lt;span class='line'&gt;15&lt;/span&gt;
&lt;span class='line'&gt;16&lt;/span&gt;
&lt;span class='line'&gt;17&lt;/span&gt;
&lt;span class='line'&gt;18&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;div class='line'&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;active_support/concern&amp;#39;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;CachedResource&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Concern&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class="n"&gt;included&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class="n"&gt;alias_method_chain&lt;/span&gt; &lt;span class="ss"&gt;:find&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:read_through_cache&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;ClassMethods&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;find_with_read_through_cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;I&amp;#39;m hijacking the find method, but not doing anything.&amp;quot;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class="n"&gt;find_without_read_through_cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;


&lt;p&gt;If you include this module in any ActiveResource class and call the &lt;code&gt;find&lt;/code&gt; method you will see that &lt;code&gt;find_with_read_through_cache&lt;/code&gt; is called and prints a message letting you know about it.&lt;/p&gt;

&lt;p&gt;In order to cache an object, we need a suitable cache key, something unique that we can use to store and retrieve the objects. A combination of the ActiveResource class name and the arguments passed to find should do just nicely:&lt;/p&gt;

&lt;div&gt;&lt;figure role=code&gt; &lt;div class="highlight"&gt;&lt;table cellpadding="0" cellspacing="0"&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;div class='line'&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;cache_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;downcase&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;


&lt;p&gt;Using &lt;code&gt;Rails.cache&lt;/code&gt; we can implement the basic read through cache algorithm quite easily. The only quirk is that we must call &lt;code&gt;dup&lt;/code&gt; on anything pulled from &lt;code&gt;Rails.cache&lt;/code&gt; that we intend to modify it later:&lt;/p&gt;

&lt;div&gt;&lt;figure role=code&gt; &lt;div class="highlight"&gt;&lt;table cellpadding="0" cellspacing="0"&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;span class='line'&gt;5&lt;/span&gt;
&lt;span class='line'&gt;6&lt;/span&gt;
&lt;span class='line'&gt;7&lt;/span&gt;
&lt;span class='line'&gt;8&lt;/span&gt;
&lt;span class='line'&gt;9&lt;/span&gt;
&lt;span class='line'&gt;10&lt;/span&gt;
&lt;span class='line'&gt;11&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;div class='line'&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;find_with_read_through_cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cache_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;try&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:dup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;find_without_read_through_cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class="n"&gt;result&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;


&lt;p&gt;If you are familiar with how &lt;code&gt;Rails.cache&lt;/code&gt; works, then you will have noticed the flaw in the above code.
The cache will be held onto for ever.
Probably not what you want as the results could change and you have no way to flush the cache.&lt;/p&gt;

&lt;p&gt;So we need a way to set the cache expiry.
A class level &lt;code&gt;cache_for&lt;/code&gt; attribute, and a &lt;code&gt;cache_expires_in&lt;/code&gt; method to retrieve the value or a default if none is provided.
Then we can pass the &lt;code&gt;:expires_in&lt;/code&gt; parameter to &lt;code&gt;Rails.cache.write&lt;/code&gt; and our simple caching strategy is complete:&lt;/p&gt;

&lt;div&gt;&lt;figure role=code&gt; &lt;div class="highlight"&gt;&lt;table cellpadding="0" cellspacing="0"&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;span class='line'&gt;5&lt;/span&gt;
&lt;span class='line'&gt;6&lt;/span&gt;
&lt;span class='line'&gt;7&lt;/span&gt;
&lt;span class='line'&gt;8&lt;/span&gt;
&lt;span class='line'&gt;9&lt;/span&gt;
&lt;span class='line'&gt;10&lt;/span&gt;
&lt;span class='line'&gt;11&lt;/span&gt;
&lt;span class='line'&gt;12&lt;/span&gt;
&lt;span class='line'&gt;13&lt;/span&gt;
&lt;span class='line'&gt;14&lt;/span&gt;
&lt;span class='line'&gt;15&lt;/span&gt;
&lt;span class='line'&gt;16&lt;/span&gt;
&lt;span class='line'&gt;17&lt;/span&gt;
&lt;span class='line'&gt;18&lt;/span&gt;
&lt;span class='line'&gt;19&lt;/span&gt;
&lt;span class='line'&gt;20&lt;/span&gt;
&lt;span class='line'&gt;21&lt;/span&gt;
&lt;span class='line'&gt;22&lt;/span&gt;
&lt;span class='line'&gt;23&lt;/span&gt;
&lt;span class='line'&gt;24&lt;/span&gt;
&lt;span class='line'&gt;25&lt;/span&gt;
&lt;span class='line'&gt;26&lt;/span&gt;
&lt;span class='line'&gt;27&lt;/span&gt;
&lt;span class='line'&gt;28&lt;/span&gt;
&lt;span class='line'&gt;29&lt;/span&gt;
&lt;span class='line'&gt;30&lt;/span&gt;
&lt;span class='line'&gt;31&lt;/span&gt;
&lt;span class='line'&gt;32&lt;/span&gt;
&lt;span class='line'&gt;33&lt;/span&gt;
&lt;span class='line'&gt;34&lt;/span&gt;
&lt;span class='line'&gt;35&lt;/span&gt;
&lt;span class='line'&gt;36&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;div class='line'&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;active_support/concern&amp;#39;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;CachedResource&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Concern&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class="n"&gt;included&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class="n"&gt;alias_method_chain&lt;/span&gt; &lt;span class="ss"&gt;:find&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:read_through_cache&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class="n"&gt;class_attribute&lt;/span&gt; &lt;span class="ss"&gt;:cache_for&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;ClassMethods&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;cache_expires_in&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache_for&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;find_with_read_through_cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cache_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;try&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:dup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;find_without_read_through_cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:expires_in&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache_expires_in&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class="n"&gt;result&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class="kp"&gt;private&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;cache_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;downcase&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;


&lt;p&gt;With this simple module we can now cache ActiveResource objects for as long as we're comfortable.&lt;/p&gt;

&lt;p&gt;I used this technique on a recent project, combined with a cron job to keep the caches warm, to ensure that pages including upwards of 30 ActiveResource objects were able to load with 100ms response times.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/inject-is-for-wizards/~4/saJX4OwYCXI" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://injectisforwizards.com/blog/read-through-caching-of-activeresource/</feedburner:origLink></entry>
  
  <entry>
    <title>Poor Design</title>
    <link href="http://feedproxy.google.com/~r/inject-is-for-wizards/~3/gBVc_cAj1Cw/" />
    <updated>2011-09-15T10:53:00+10:00</updated>
    <id>http://injectisforwizards.com/blog/poor-design</id>
    <content type="html">&lt;p&gt;I hate my salt and pepper shakers.&lt;/p&gt;

&lt;p&gt;&lt;img class='' src='http://injectisforwizards.com/images/2011-09-15-poor-design/salt-and-pepper-1.jpg' width='' height='' alt='Salt and Pepper Shakers Side on' title='Salt and Pepper Shakers Side on'&gt;&lt;/p&gt;

&lt;p&gt;I always use the wrong one. I've had them for nearly two years, and I still always reach for the wrong one.&lt;/p&gt;

&lt;p&gt;&lt;img class='' src='http://injectisforwizards.com/images/2011-09-15-poor-design/salt-and-pepper-2.jpg' width='' height='' alt='Salt and Pepper Shakers Top View' title='Salt and Pepper Shakers Top View'&gt;&lt;/p&gt;

&lt;p&gt;You see, the pepper is in the red shaker, not the black.
When I think of pepper, I think of black pepper, therefore I instinctively reach for the black shaker.
The visual queues given to me by the colour of the shakers don't align with reality of what's inside them.&lt;/p&gt;

&lt;p&gt;I hate my salt and pepper shakers, they make me feel stupid.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/inject-is-for-wizards/~4/gBVc_cAj1Cw" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://injectisforwizards.com/blog/poor-design/</feedburner:origLink></entry>
  
  <entry>
    <title>Unit Tests Should Not Write to the Database</title>
    <link href="http://feedproxy.google.com/~r/inject-is-for-wizards/~3/5wyWkn5kO1g/" />
    <updated>2011-09-07T19:11:00+10:00</updated>
    <id>http://injectisforwizards.com/blog/unit-tests-should-not-write-to-the-database</id>
    <content type="html">&lt;p&gt;As a rails developer, I've become accustomed to writing tests that interact with the database.
Over the years I've transitioned from using fixtures, to using factories, when generating test data.
Tools like &lt;a href="https://github.com/notahat/machinist"&gt;machinist&lt;/a&gt; make generating dynamic test data dead simple and repeatable.
I think it's time to stop, and here's why:&lt;/p&gt;

&lt;h3&gt;Database access is slow&lt;/h3&gt;

&lt;p&gt;Reading and writing from a database is slow when compared to manipulating objects in memory.
Most of the time, you don't actually need an object in the database to unit test it properly.&lt;/p&gt;

&lt;h3&gt;Object Graphs&lt;/h3&gt;

&lt;p&gt;Machinist makes generating test data easy, it makes it even easier to build complex object graphs with one line of code.
Hands up if you've ever wondered why your tests are grinding to a halt only to realise one line of code is generating, validating and saving 30 objects you don't really care about?
It's just too easy to build yourself a mess.&lt;/p&gt;

&lt;h3&gt;Cleaner, Focused Tests.&lt;/h3&gt;

&lt;p&gt;With no object graph to distract you, you're left with only one option: write small focused unit tests.&lt;/p&gt;

&lt;h3&gt;How?&lt;/h3&gt;

&lt;p&gt;In a side project of mine I decided to do an experiment, could I force myself to write model tests that never touch the database?
Leaving integration tests to manipulate the full system, and thus build large object graphs.&lt;/p&gt;

&lt;p&gt;I don't trust myself at the best of times, so I duck punched ActiveRecord to raise a custom exception on any attempt to execute an insert statement.&lt;/p&gt;

&lt;div&gt;&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;Making ActiveRecord Raise on Insert Statements  (active_record_database_unavailable.rb)&lt;/span&gt; &lt;a href='http://injectisforwizards.com/downloads/code/active_record_database_unavailable.rb'&gt;download&lt;/a&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table cellpadding="0" cellspacing="0"&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;span class='line'&gt;5&lt;/span&gt;
&lt;span class='line'&gt;6&lt;/span&gt;
&lt;span class='line'&gt;7&lt;/span&gt;
&lt;span class='line'&gt;8&lt;/span&gt;
&lt;span class='line'&gt;9&lt;/span&gt;
&lt;span class='line'&gt;10&lt;/span&gt;
&lt;span class='line'&gt;11&lt;/span&gt;
&lt;span class='line'&gt;12&lt;/span&gt;
&lt;span class='line'&gt;13&lt;/span&gt;
&lt;span class='line'&gt;14&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;div class='line'&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;ActiveRecord&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DatabaseUnavailable&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecordError&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;ConnectionAdapters&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AbstractAdapter&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;exec_insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;binds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;DatabaseUnavailable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Writing to the database makes for slow unit tests&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;


&lt;h3&gt;The Result?&lt;/h3&gt;

&lt;p&gt;Really fast unit tests, that test one thing in isolation, like they're supposed to.
Coupled with really slow integration tests, that exercise the full system stack.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/inject-is-for-wizards/~4/5wyWkn5kO1g" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://injectisforwizards.com/blog/unit-tests-should-not-write-to-the-database/</feedburner:origLink></entry>
  
  <entry>
    <title>Indistinguishable From Magic</title>
    <link href="http://feedproxy.google.com/~r/inject-is-for-wizards/~3/RazebZOG3Dw/" />
    <updated>2011-08-31T21:16:00+10:00</updated>
    <id>http://injectisforwizards.com/blog/indistinguishable-from-magic</id>
    <content type="html">&lt;p&gt;My friend, &lt;a href="http://twitter.com/#!/crafterm"&gt;Marcus Crafter&lt;/a&gt;, once told me: &lt;em&gt;inject is for wizards&lt;/em&gt;.
He was refering to the &lt;a href="http://www.ruby-doc.org/core/classes/Enumerable.html#M001494"&gt;inject&lt;/a&gt; method from Ruby's enumerable module.&lt;/p&gt;

&lt;p&gt;It reminded me of the following quote:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Any sufficiently advanced technology is indistinguishable from magic.&lt;/p&gt;&lt;footer&gt;&lt;strong&gt;Arthur C. Clarke&lt;/strong&gt;&lt;cite&gt;Third Law of Prediction&lt;/cite&gt;&lt;/footer&gt;&lt;/blockquote&gt;


&lt;p&gt;The inject method of course, has nothing to do with magic, it just seems that way to the uninitiated.
People new to the ruby language avoid it, looking up the documentation every time they encounter it.
Eventually, through repeated exposure, the use of inject becomes second nature.&lt;/p&gt;

&lt;p&gt;As a software developer, this journey from a complete lack of understanding, through to all powerful wizardry happens on a near daily basis.
Join me in a journey from stupidity to sorcery, or something like that.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/inject-is-for-wizards/~4/RazebZOG3Dw" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://injectisforwizards.com/blog/indistinguishable-from-magic/</feedburner:origLink></entry>
  
</feed>

