revo-cache_fu 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +0 -0
- data/LICENSE +18 -0
- data/README +17 -0
- data/Rakefile +54 -0
- data/VERSION +1 -0
- data/cache_fu.gemspec +77 -0
- data/defaults/extensions.rb.default +40 -0
- data/defaults/memcached.yml.default +34 -0
- data/defaults/memcached_ctl.default +81 -0
- data/init.rb +34 -0
- data/install.rb +58 -0
- data/lib/acts_as_cached/benchmarking.rb +87 -0
- data/lib/acts_as_cached/cache_methods.rb +305 -0
- data/lib/acts_as_cached/config.rb +97 -0
- data/lib/acts_as_cached/disabled.rb +30 -0
- data/lib/acts_as_cached/fragment_cache.rb +124 -0
- data/lib/acts_as_cached/local_cache.rb +44 -0
- data/lib/acts_as_cached/memcached_rails.rb +17 -0
- data/lib/acts_as_cached/recipes.rb +8 -0
- data/lib/acts_as_cached.rb +51 -0
- data/tasks/memcached.rake +43 -0
- data/test/benchmarking_test.rb +36 -0
- data/test/cache_test.rb +281 -0
- data/test/config_test.rb +128 -0
- data/test/disabled_test.rb +40 -0
- data/test/extensions_test.rb +33 -0
- data/test/fragment_cache_test.rb +250 -0
- data/test/helper.rb +215 -0
- data/test/local_cache_test.rb +43 -0
- data/test/sti_test.rb +36 -0
- metadata +92 -0
| @@ -0,0 +1,250 @@ | |
| 1 | 
            +
            require File.join(File.dirname(__FILE__), 'helper')
         | 
| 2 | 
            +
            require 'test/unit'
         | 
| 3 | 
            +
            require 'action_controller/test_process'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            ActionController::Routing::Routes.draw do |map|
         | 
| 6 | 
            +
              map.connect ':controller/:action/:id'
         | 
| 7 | 
            +
            end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            class FooController < ActionController::Base
         | 
| 10 | 
            +
              def url_for(*args)
         | 
| 11 | 
            +
                "http://#{Time.now.to_i}.foo.com"
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
            end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            class BarController < ActionController::Base
         | 
| 16 | 
            +
              def page
         | 
| 17 | 
            +
                render :text => "give me my bongos"
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
              
         | 
| 20 | 
            +
              def index
         | 
| 21 | 
            +
                render :text => "doop!"
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
              
         | 
| 24 | 
            +
              def edit
         | 
| 25 | 
            +
                render :text => "rawk"
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              def trees_are_swell?
         | 
| 29 | 
            +
                true
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              def rescue_action(e)
         | 
| 33 | 
            +
                raise e
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
            end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
            class FooTemplate
         | 
| 38 | 
            +
              include ::ActionView::Helpers::CacheHelper
         | 
| 39 | 
            +
              
         | 
| 40 | 
            +
              attr_reader :controller
         | 
| 41 | 
            +
             | 
| 42 | 
            +
              def initialize
         | 
| 43 | 
            +
                @controller = FooController.new
         | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
            end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
            context "Fragment caching (when used with memcached)" do
         | 
| 48 | 
            +
              include FragmentCacheSpecSetup
         | 
| 49 | 
            +
              
         | 
| 50 | 
            +
              setup do
         | 
| 51 | 
            +
                @view = FooTemplate.new
         | 
| 52 | 
            +
              end
         | 
| 53 | 
            +
              
         | 
| 54 | 
            +
              specify "should be able to cache with a normal, non-keyed Rails cache calls" do
         | 
| 55 | 
            +
                _erbout = ""
         | 
| 56 | 
            +
                content = "Caching is fun!"
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                ActsAsCached.config[:store].expects(:set).with(@view.controller.url_for.gsub('http://',''), content, ActsAsCached.config[:ttl])
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                @view.cache { _erbout << content }
         | 
| 61 | 
            +
              end
         | 
| 62 | 
            +
              
         | 
| 63 | 
            +
              specify "should be able to cache with a normal cache call when we don't have a default ttl" do
         | 
| 64 | 
            +
                begin
         | 
| 65 | 
            +
                  _erbout = ""
         | 
| 66 | 
            +
                  content = "Caching is fun!"
         | 
| 67 | 
            +
                
         | 
| 68 | 
            +
                  original_ttl = ActsAsCached.config.delete(:ttl)
         | 
| 69 | 
            +
                  ActsAsCached.config[:store].expects(:set).with(@view.controller.url_for.gsub('http://',''), content, 25.minutes)
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                  @view.cache { _erbout << content }
         | 
| 72 | 
            +
                ensure
         | 
| 73 | 
            +
                  ActsAsCached.config[:ttl] = original_ttl
         | 
| 74 | 
            +
                end
         | 
| 75 | 
            +
              end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
              specify "should be able to cache with a normal, keyed Rails cache calls" do
         | 
| 78 | 
            +
                _erbout = ""
         | 
| 79 | 
            +
                content = "Wow, even a key?!"
         | 
| 80 | 
            +
                key = "#{Time.now.to_i}_wow_key"
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                ActsAsCached.config[:store].expects(:set).with(key, content, ActsAsCached.config[:ttl])
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                @view.cache(key) { _erbout << content } 
         | 
| 85 | 
            +
              end
         | 
| 86 | 
            +
              
         | 
| 87 | 
            +
              specify "should be able to cache with new time-to-live option" do 
         | 
| 88 | 
            +
                _erbout = ""
         | 
| 89 | 
            +
                content = "Time to live?  TIME TO DIE!!"
         | 
| 90 | 
            +
                key = "#{Time.now.to_i}_death_key"
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                ActsAsCached.config[:store].expects(:set).with(key, content, 60)
         | 
| 93 | 
            +
                @view.cache(key, { :ttl => 60 }) { _erbout << content }
         | 
| 94 | 
            +
              end
         | 
| 95 | 
            +
             | 
| 96 | 
            +
              specify "should ignore everything but time-to-live when options are present" do 
         | 
| 97 | 
            +
                _erbout = ""
         | 
| 98 | 
            +
                content = "Don't mess around, here, sir."
         | 
| 99 | 
            +
                key = "#{Time.now.to_i}_mess_key"
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                ActsAsCached.config[:store].expects(:set).with(key, content, 60)
         | 
| 102 | 
            +
                @view.cache(key, { :other_options => "for the kids", :ttl => 60 }) { _erbout << content } 
         | 
| 103 | 
            +
              end
         | 
| 104 | 
            +
              
         | 
| 105 | 
            +
              specify "should be able to skip cache gets" do
         | 
| 106 | 
            +
                ActsAsCached.skip_cache_gets = true
         | 
| 107 | 
            +
                ActsAsCached.config[:store].expects(:get).never
         | 
| 108 | 
            +
                _erbout = ""
         | 
| 109 | 
            +
                @view.cache { _erbout << "Caching is fun!" }
         | 
| 110 | 
            +
                ActsAsCached.skip_cache_gets = false
         | 
| 111 | 
            +
              end
         | 
| 112 | 
            +
            end
         | 
| 113 | 
            +
             | 
| 114 | 
            +
            context "Action caching (when used with memcached)" do
         | 
| 115 | 
            +
              include FragmentCacheSpecSetup
         | 
| 116 | 
            +
              page_content = "give me my bongos"
         | 
| 117 | 
            +
              index_content = "doop!"
         | 
| 118 | 
            +
              edit_content = "rawk"
         | 
| 119 | 
            +
              
         | 
| 120 | 
            +
              setup do
         | 
| 121 | 
            +
                @controller = BarController.new
         | 
| 122 | 
            +
                @request    = ActionController::TestRequest.new
         | 
| 123 | 
            +
                @response   = ActionController::TestResponse.new
         | 
| 124 | 
            +
              end
         | 
| 125 | 
            +
              
         | 
| 126 | 
            +
              teardown do # clear the filter chain between specs to avoid chaos
         | 
| 127 | 
            +
                BarController.write_inheritable_attribute('filter_chain', [])
         | 
| 128 | 
            +
              end
         | 
| 129 | 
            +
              
         | 
| 130 | 
            +
              # little helper for prettier expections on the cache
         | 
| 131 | 
            +
              def cache_expects(method, expected_times = 1)
         | 
| 132 | 
            +
                ActsAsCached.config[:store].expects(method).times(expected_times)
         | 
| 133 | 
            +
              end
         | 
| 134 | 
            +
             | 
| 135 | 
            +
              specify "should cache using default ttl for a normal action cache without ttl" do
         | 
| 136 | 
            +
                BarController.caches_action :page
         | 
| 137 | 
            +
             | 
| 138 | 
            +
                key = 'test.host/bar/page'
         | 
| 139 | 
            +
                cache_expects(:set).with(key, page_content, ActsAsCached.config[:ttl])
         | 
| 140 | 
            +
                get :page
         | 
| 141 | 
            +
                @response.body.should == page_content
         | 
| 142 | 
            +
                
         | 
| 143 | 
            +
                cache_expects(:read).with(key, nil).returns(page_content)
         | 
| 144 | 
            +
                get :page
         | 
| 145 | 
            +
                @response.body.should == page_content
         | 
| 146 | 
            +
              end
         | 
| 147 | 
            +
              
         | 
| 148 | 
            +
              specify "should cache using defaul ttl for normal, multiple action caches" do
         | 
| 149 | 
            +
                BarController.caches_action :page, :index
         | 
| 150 | 
            +
                
         | 
| 151 | 
            +
                cache_expects(:set).with('test.host/bar/page', page_content, ActsAsCached.config[:ttl])
         | 
| 152 | 
            +
                get :page
         | 
| 153 | 
            +
                cache_expects(:set).with('test.host/bar', index_content, ActsAsCached.config[:ttl])
         | 
| 154 | 
            +
                get :index
         | 
| 155 | 
            +
              end
         | 
| 156 | 
            +
              
         | 
| 157 | 
            +
              specify "should be able to action cache with ttl" do
         | 
| 158 | 
            +
                BarController.caches_action :page => { :ttl => 2.minutes }
         | 
| 159 | 
            +
             | 
| 160 | 
            +
                cache_expects(:set).with('test.host/bar/page', page_content, 2.minutes)
         | 
| 161 | 
            +
                get :page
         | 
| 162 | 
            +
                @response.body.should == page_content
         | 
| 163 | 
            +
              end
         | 
| 164 | 
            +
              
         | 
| 165 | 
            +
              specify "should be able to action cache multiple actions with ttls" do
         | 
| 166 | 
            +
                BarController.caches_action :index, :page => { :ttl => 5.minutes }
         | 
| 167 | 
            +
                
         | 
| 168 | 
            +
                cache_expects(:set).with('test.host/bar/page', page_content, 5.minutes)
         | 
| 169 | 
            +
                cache_expects(:set).with('test.host/bar', index_content, ActsAsCached.config[:ttl])
         | 
| 170 | 
            +
                
         | 
| 171 | 
            +
                get :page
         | 
| 172 | 
            +
                @response.body.should == page_content
         | 
| 173 | 
            +
             | 
| 174 | 
            +
                get :index
         | 
| 175 | 
            +
                @response.body.should == index_content
         | 
| 176 | 
            +
                cache_expects(:read).with('test.host/bar', nil).returns(index_content)
         | 
| 177 | 
            +
             | 
| 178 | 
            +
                get :index
         | 
| 179 | 
            +
              end
         | 
| 180 | 
            +
             | 
| 181 | 
            +
              specify "should be able to action cache conditionally when passed something that returns true" do
         | 
| 182 | 
            +
                BarController.caches_action :page => { :if => :trees_are_swell? }
         | 
| 183 | 
            +
                
         | 
| 184 | 
            +
                cache_expects(:set).with('test.host/bar/page', page_content, ActsAsCached.config[:ttl])
         | 
| 185 | 
            +
                
         | 
| 186 | 
            +
                get :page
         | 
| 187 | 
            +
                @response.body.should == page_content
         | 
| 188 | 
            +
             | 
| 189 | 
            +
                cache_expects(:read).with('test.host/bar/page', nil).returns(page_content)
         | 
| 190 | 
            +
             | 
| 191 | 
            +
                get :page
         | 
| 192 | 
            +
              end
         | 
| 193 | 
            +
             | 
| 194 | 
            +
              #check for edginess
         | 
| 195 | 
            +
              if [].respond_to?(:extract_options!)
         | 
| 196 | 
            +
                specify "should not break cache_path overrides" do
         | 
| 197 | 
            +
                  BarController.caches_action :page, :cache_path => 'http://test.host/some/custom/path'
         | 
| 198 | 
            +
                  cache_expects(:set).with('test.host/some/custom/path', page_content, ActsAsCached.config[:ttl])
         | 
| 199 | 
            +
                  get :page
         | 
| 200 | 
            +
                end
         | 
| 201 | 
            +
              
         | 
| 202 | 
            +
                specify "should not break cache_path block overrides" do
         | 
| 203 | 
            +
                  BarController.caches_action :edit, :cache_path => Proc.new { |c| c.params[:id] ? "http://test.host/#{c.params[:id]}/edit" : "http://test.host/edit" }
         | 
| 204 | 
            +
                  cache_expects(:set).with('test.host/edit', edit_content, ActsAsCached.config[:ttl])
         | 
| 205 | 
            +
                  get :edit
         | 
| 206 | 
            +
             | 
| 207 | 
            +
                  get :index
         | 
| 208 | 
            +
                  cache_expects(:set).with('test.host/5/edit', edit_content, ActsAsCached.config[:ttl])
         | 
| 209 | 
            +
                  get :edit, :id => 5
         | 
| 210 | 
            +
                end
         | 
| 211 | 
            +
              
         | 
| 212 | 
            +
                specify "should play nice with custom ttls and cache_path overrides" do 
         | 
| 213 | 
            +
                  BarController.caches_action :page => { :ttl => 5.days }, :cache_path => 'http://test.host/my/custom/path'
         | 
| 214 | 
            +
                  cache_expects(:set).with('test.host/my/custom/path', page_content, 5.days)
         | 
| 215 | 
            +
                  get :page
         | 
| 216 | 
            +
                end
         | 
| 217 | 
            +
              
         | 
| 218 | 
            +
                specify "should play nice with custom ttls and cache_path block overrides" do 
         | 
| 219 | 
            +
                  BarController.caches_action :edit, :cache_path => Proc.new { |c| c.params[:id] ? "http://test.host/#{c.params[:id]}/edit" : "http://test.host/edit" }
         | 
| 220 | 
            +
                  cache_expects(:set).with('test.host/5/edit', edit_content, ActsAsCached.config[:ttl])
         | 
| 221 | 
            +
                  get :edit, :id => 5
         | 
| 222 | 
            +
                end
         | 
| 223 | 
            +
                
         | 
| 224 | 
            +
                specify "should play nice with the most complicated thing i can throw at it" do 
         | 
| 225 | 
            +
                  BarController.caches_action :index => { :ttl => 24.hours }, :page => { :ttl => 5.seconds }, :edit => { :ttl => 5.days }, :cache_path => Proc.new { |c| c.params[:id] ? "http://test.host/#{c.params[:id]}/#{c.params[:action]}" : "http://test.host/#{c.params[:action]}" }
         | 
| 226 | 
            +
                  cache_expects(:set).with('test.host/index', index_content, 24.hours)
         | 
| 227 | 
            +
                  get :index
         | 
| 228 | 
            +
                  cache_expects(:set).with('test.host/5/edit', edit_content, 5.days)
         | 
| 229 | 
            +
                  get :edit, :id => 5
         | 
| 230 | 
            +
                  cache_expects(:set).with('test.host/5/page', page_content, 5.seconds)
         | 
| 231 | 
            +
                  get :page, :id => 5
         | 
| 232 | 
            +
                  
         | 
| 233 | 
            +
                  cache_expects(:read).with('test.host/5/page', nil).returns(page_content)
         | 
| 234 | 
            +
                  get :page, :id => 5
         | 
| 235 | 
            +
                  cache_expects(:read).with('test.host/5/edit', nil).returns(edit_content)
         | 
| 236 | 
            +
                  get :edit, :id => 5
         | 
| 237 | 
            +
                  cache_expects(:read).with('test.host/index', nil).returns(index_content)
         | 
| 238 | 
            +
                  get :index
         | 
| 239 | 
            +
                end
         | 
| 240 | 
            +
              end
         | 
| 241 | 
            +
             | 
| 242 | 
            +
              specify "should be able to skip action caching when passed something that returns false" do
         | 
| 243 | 
            +
                BarController.caches_action :page => { :if => Proc.new {|c| !c.trees_are_swell?} }
         | 
| 244 | 
            +
                
         | 
| 245 | 
            +
                cache_expects(:set, 0).with('test.host/bar/page', page_content, ActsAsCached.config[:ttl])
         | 
| 246 | 
            +
                
         | 
| 247 | 
            +
                get :page
         | 
| 248 | 
            +
                @response.body.should == page_content
         | 
| 249 | 
            +
              end
         | 
| 250 | 
            +
            end
         | 
    
        data/test/helper.rb
    ADDED
    
    | @@ -0,0 +1,215 @@ | |
| 1 | 
            +
            ##
         | 
| 2 | 
            +
            # This file exists to fake out all the Railsisms we use so we can run the 
         | 
| 3 | 
            +
            # tests in isolation.
         | 
| 4 | 
            +
            $LOAD_PATH.unshift 'lib/'
         | 
| 5 | 
            +
            # 
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            begin
         | 
| 8 | 
            +
              require 'rubygems'
         | 
| 9 | 
            +
              gem 'mocha', '>= 0.4.0'
         | 
| 10 | 
            +
              require 'mocha'
         | 
| 11 | 
            +
              gem 'test-spec', '= 0.3.0'
         | 
| 12 | 
            +
              require 'test/spec'
         | 
| 13 | 
            +
              require 'multi_rails_init'
         | 
| 14 | 
            +
            rescue LoadError
         | 
| 15 | 
            +
              puts '=> acts_as_cached tests depend on the following gems: mocha (0.4.0+), test-spec (0.3.0), multi_rails (0.0.2), and rails.'
         | 
| 16 | 
            +
            end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            begin
         | 
| 19 | 
            +
              require 'redgreen'
         | 
| 20 | 
            +
            rescue LoadError
         | 
| 21 | 
            +
              nil
         | 
| 22 | 
            +
            end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            Test::Spec::Should.send    :alias_method, :have, :be
         | 
| 25 | 
            +
            Test::Spec::ShouldNot.send :alias_method, :have, :be
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            ##
         | 
| 28 | 
            +
            # real men test without mocks
         | 
| 29 | 
            +
            if $with_memcache = ARGV.include?('with-memcache')
         | 
| 30 | 
            +
              require 'memcache'
         | 
| 31 | 
            +
            end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
            ##
         | 
| 34 | 
            +
            # init.rb hacks
         | 
| 35 | 
            +
            RAILS_ROOT = '.'    unless defined? RAILS_ROOT
         | 
| 36 | 
            +
            RAILS_ENV  = 'test' unless defined? RAILS_ENV
         | 
| 37 | 
            +
             | 
| 38 | 
            +
            ##
         | 
| 39 | 
            +
            # get the default config using absolute path, so tests all play nice when run in isolation
         | 
| 40 | 
            +
            DEFAULT_CONFIG_FILE = File.expand_path(File.dirname(__FILE__) + '/../defaults/memcached.yml.default')
         | 
| 41 | 
            +
             | 
| 42 | 
            +
            ##
         | 
| 43 | 
            +
            # aac
         | 
| 44 | 
            +
            require 'acts_as_cached'
         | 
| 45 | 
            +
            Object.send :include, ActsAsCached::Mixin
         | 
| 46 | 
            +
             | 
| 47 | 
            +
            ##
         | 
| 48 | 
            +
            # i need you.
         | 
| 49 | 
            +
            module Enumerable
         | 
| 50 | 
            +
              def index_by
         | 
| 51 | 
            +
                inject({}) do |accum, elem|
         | 
| 52 | 
            +
                  accum[yield(elem)] = elem
         | 
| 53 | 
            +
                  accum
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
              end
         | 
| 56 | 
            +
            end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
            ##
         | 
| 59 | 
            +
            # mocky.
         | 
| 60 | 
            +
            class HashStore < Hash
         | 
| 61 | 
            +
              alias :get :[]
         | 
| 62 | 
            +
             | 
| 63 | 
            +
              def get_multi(*values)
         | 
| 64 | 
            +
                reject { |k,v| !values.include? k }
         | 
| 65 | 
            +
              end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
              def set(key, value, *others)
         | 
| 68 | 
            +
                self[key] = value
         | 
| 69 | 
            +
              end
         | 
| 70 | 
            +
              
         | 
| 71 | 
            +
              def namespace
         | 
| 72 | 
            +
                nil
         | 
| 73 | 
            +
              end
         | 
| 74 | 
            +
            end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
            $cache = HashStore.new
         | 
| 77 | 
            +
             | 
| 78 | 
            +
            class Story
         | 
| 79 | 
            +
              acts_as_cached($with_memcache ? {} : { :store => $cache })
         | 
| 80 | 
            +
             | 
| 81 | 
            +
              attr_accessor :id, :title
         | 
| 82 | 
            +
             | 
| 83 | 
            +
              def initialize(attributes = {})
         | 
| 84 | 
            +
                attributes.each { |key, value| instance_variable_set("@#{key}", value) }
         | 
| 85 | 
            +
              end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
              def attributes
         | 
| 88 | 
            +
                { :id => id, :title => title }
         | 
| 89 | 
            +
              end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
              def ==(other)
         | 
| 92 | 
            +
                return false unless other.respond_to? :attributes
         | 
| 93 | 
            +
                attributes == other.attributes
         | 
| 94 | 
            +
              end
         | 
| 95 | 
            +
             | 
| 96 | 
            +
              def self.find(*args) 
         | 
| 97 | 
            +
                options = args.last.is_a?(Hash) ? args.pop : {}
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                if (ids = args.flatten).size > 1
         | 
| 100 | 
            +
                  ids.map { |id| $stories[id.to_i] }
         | 
| 101 | 
            +
                elsif (id = args.flatten.first).to_i.to_s == id.to_s
         | 
| 102 | 
            +
                  $stories[id.to_i]
         | 
| 103 | 
            +
                end
         | 
| 104 | 
            +
              end
         | 
| 105 | 
            +
              
         | 
| 106 | 
            +
              def self.find_by_title(*args)
         | 
| 107 | 
            +
                title = args.shift
         | 
| 108 | 
            +
                find(args).select { |s| s.title == title }
         | 
| 109 | 
            +
              end
         | 
| 110 | 
            +
             | 
| 111 | 
            +
              def self.base_class
         | 
| 112 | 
            +
                Story
         | 
| 113 | 
            +
              end
         | 
| 114 | 
            +
             | 
| 115 | 
            +
              def self.something_cool; :redbull end
         | 
| 116 | 
            +
              def something_flashy;    :molassy end
         | 
| 117 | 
            +
             | 
| 118 | 
            +
              def self.block_on(target = nil)
         | 
| 119 | 
            +
                target || :something
         | 
| 120 | 
            +
              end
         | 
| 121 | 
            +
             | 
| 122 | 
            +
              def self.pass_through(target)
         | 
| 123 | 
            +
                target
         | 
| 124 | 
            +
              end
         | 
| 125 | 
            +
             | 
| 126 | 
            +
              def self.two_params(first, second)
         | 
| 127 | 
            +
                "first: #{first} | second: #{second}"
         | 
| 128 | 
            +
              end
         | 
| 129 | 
            +
             | 
| 130 | 
            +
              def self.find_live(*args) false end
         | 
| 131 | 
            +
            end
         | 
| 132 | 
            +
             | 
| 133 | 
            +
            class Feature   < Story; end
         | 
| 134 | 
            +
            class Interview < Story; end
         | 
| 135 | 
            +
             | 
| 136 | 
            +
            module ActionController
         | 
| 137 | 
            +
              class Base
         | 
| 138 | 
            +
                def rendering_runtime(*args) '' end
         | 
| 139 | 
            +
                def self.silence; yield end
         | 
| 140 | 
            +
              end
         | 
| 141 | 
            +
            end
         | 
| 142 | 
            +
             | 
| 143 | 
            +
            class MemCache
         | 
| 144 | 
            +
              attr_accessor :servers
         | 
| 145 | 
            +
              def initialize(*args) end
         | 
| 146 | 
            +
              class MemCacheError < StandardError; end unless defined? MemCacheError
         | 
| 147 | 
            +
            end unless $with_memcache
         | 
| 148 | 
            +
             | 
| 149 | 
            +
            module StoryCacheSpecSetup
         | 
| 150 | 
            +
              def self.included(base)
         | 
| 151 | 
            +
                base.setup do 
         | 
| 152 | 
            +
                  setup_cache_spec 
         | 
| 153 | 
            +
                  Story.instance_eval { @max_key_length = nil }
         | 
| 154 | 
            +
                end
         | 
| 155 | 
            +
              end
         | 
| 156 | 
            +
             | 
| 157 | 
            +
              def setup_cache_spec
         | 
| 158 | 
            +
                @story  = Story.new(:id => 1, :title => "acts_as_cached 2 released!")
         | 
| 159 | 
            +
                @story2 = Story.new(:id => 2, :title => "BDD is something you can use")
         | 
| 160 | 
            +
                @story3 = Story.new(:id => 3, :title => "RailsConf is overrated.")
         | 
| 161 | 
            +
                $stories = { 1 => @story, 2 => @story2, 3 => @story3 }
         | 
| 162 | 
            +
             | 
| 163 | 
            +
                $with_memcache ? with_memcache : with_mock
         | 
| 164 | 
            +
              end
         | 
| 165 | 
            +
             | 
| 166 | 
            +
              def with_memcache
         | 
| 167 | 
            +
                unless $mc_setup_for_story_cache_spec
         | 
| 168 | 
            +
                  ActsAsCached.config.clear
         | 
| 169 | 
            +
                  config = YAML.load_file(DEFAULT_CONFIG_FILE)
         | 
| 170 | 
            +
                  config['test'] = config['development'].merge('benchmarking' => false, 'disabled' => false)
         | 
| 171 | 
            +
                  ActsAsCached.config = config
         | 
| 172 | 
            +
                  $mc_setup_for_story_cache_spec = true
         | 
| 173 | 
            +
                end
         | 
| 174 | 
            +
             | 
| 175 | 
            +
                Story.send :acts_as_cached
         | 
| 176 | 
            +
                Story.expire_cache(1)
         | 
| 177 | 
            +
                Story.expire_cache(2)
         | 
| 178 | 
            +
                Story.expire_cache(3)
         | 
| 179 | 
            +
                Story.expire_cache(:block)
         | 
| 180 | 
            +
                Story.set_cache(2, @story2)
         | 
| 181 | 
            +
              end
         | 
| 182 | 
            +
             | 
| 183 | 
            +
              def with_mock
         | 
| 184 | 
            +
                $cache.clear
         | 
| 185 | 
            +
             | 
| 186 | 
            +
                Story.send :acts_as_cached, :store => $cache
         | 
| 187 | 
            +
                $cache['Story:2'] = @story2
         | 
| 188 | 
            +
              end
         | 
| 189 | 
            +
            end
         | 
| 190 | 
            +
             | 
| 191 | 
            +
            module FragmentCacheSpecSetup
         | 
| 192 | 
            +
              def self.included(base)
         | 
| 193 | 
            +
                base.setup { setup_fragment_spec }
         | 
| 194 | 
            +
              end
         | 
| 195 | 
            +
              
         | 
| 196 | 
            +
              def setup_fragment_spec
         | 
| 197 | 
            +
                unless $mc_setup_for_fragment_cache_spec
         | 
| 198 | 
            +
                  ActsAsCached.config.clear
         | 
| 199 | 
            +
                  config = YAML.load_file(DEFAULT_CONFIG_FILE)
         | 
| 200 | 
            +
             | 
| 201 | 
            +
                  if $with_memcache
         | 
| 202 | 
            +
                    other_options = { 'fragments' => true }
         | 
| 203 | 
            +
                  else
         | 
| 204 | 
            +
                    Object.const_set(:CACHE, $cache) unless defined? CACHE
         | 
| 205 | 
            +
                    other_options = { 'fragments' => true, 'store' => $cache }
         | 
| 206 | 
            +
                  end
         | 
| 207 | 
            +
             | 
| 208 | 
            +
                  config['test'] = config['development'].merge other_options
         | 
| 209 | 
            +
             | 
| 210 | 
            +
                  ActsAsCached.config = config
         | 
| 211 | 
            +
                  ActsAsCached::FragmentCache.setup!
         | 
| 212 | 
            +
                  $mc_setup_for_fragment_cache_spec = true
         | 
| 213 | 
            +
                end
         | 
| 214 | 
            +
              end
         | 
| 215 | 
            +
            end
         | 
| @@ -0,0 +1,43 @@ | |
| 1 | 
            +
            require File.join(File.dirname(__FILE__), 'helper')
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            context "When local_cache_for_request is called" do
         | 
| 4 | 
            +
              include StoryCacheSpecSetup
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              setup do
         | 
| 7 | 
            +
                ActionController::Base.new.local_cache_for_request
         | 
| 8 | 
            +
                $cache = CACHE if $with_memcache
         | 
| 9 | 
            +
              end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              specify "get_cache should pull from the local cache on a second hit" do
         | 
| 12 | 
            +
                $cache.expects(:get).with('Story:2').returns(@story2)
         | 
| 13 | 
            +
                @story2.get_cache
         | 
| 14 | 
            +
                $cache.expects(:get).never
         | 
| 15 | 
            +
                @story2.get_cache
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              specify "set_cache should set to the local cache" do
         | 
| 19 | 
            +
                $cache.expects(:set).at_least_once.returns(@story)
         | 
| 20 | 
            +
                ActsAsCached::LocalCache.local_cache.expects(:[]=).with('Story:1', @story).returns(@story)
         | 
| 21 | 
            +
                @story.set_cache
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              specify "expire_cache should clear from the local cache" do
         | 
| 25 | 
            +
                @story2.get_cache
         | 
| 26 | 
            +
                $cache.expects(:delete).at_least_once
         | 
| 27 | 
            +
                ActsAsCached::LocalCache.local_cache.expects(:delete).with('Story:2')
         | 
| 28 | 
            +
                @story2.expire_cache
         | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
              specify "clear_cache should clear from the local cache" do
         | 
| 32 | 
            +
                @story2.get_cache
         | 
| 33 | 
            +
                $cache.expects(:delete).at_least_once
         | 
| 34 | 
            +
                ActsAsCached::LocalCache.local_cache.expects(:delete).with('Story:2')
         | 
| 35 | 
            +
                @story2.clear_cache
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
              specify "cached? should check the local cache" do
         | 
| 39 | 
            +
                @story2.get_cache
         | 
| 40 | 
            +
                $cache.expects(:get).never
         | 
| 41 | 
            +
                @story2.cached?
         | 
| 42 | 
            +
              end
         | 
| 43 | 
            +
            end
         | 
    
        data/test/sti_test.rb
    ADDED
    
    | @@ -0,0 +1,36 @@ | |
| 1 | 
            +
            require File.join(File.dirname(__FILE__), 'helper')
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            context "An STI subclass acting as cached" do
         | 
| 4 | 
            +
              include StoryCacheSpecSetup
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              setup do
         | 
| 7 | 
            +
                @feature   = Feature.new(:id => 3, :title => 'Behind the scenes of acts_as_cached')
         | 
| 8 | 
            +
                @interview = Interview.new(:id => 4, :title => 'An interview with the Arcade Fire')
         | 
| 9 | 
            +
                @feature.expire_cache
         | 
| 10 | 
            +
                @interview.expire_cache
         | 
| 11 | 
            +
                $stories.update 3 => @feature, 4 => @interview
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              specify "should be just as retrievable as any other cachable Ruby object" do
         | 
| 15 | 
            +
                Feature.cached?(3).should.equal false
         | 
| 16 | 
            +
                Feature.get_cache(3)
         | 
| 17 | 
            +
                Feature.cached?(3).should.equal true
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              specify "should have a key corresponding to its parent class" do
         | 
| 21 | 
            +
                @feature.cache_key.should.equal "Story:3"
         | 
| 22 | 
            +
                @interview.cache_key.should.equal "Story:4"
         | 
| 23 | 
            +
              end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
              specify "should be able to get itself from the cache via its parent class" do
         | 
| 26 | 
            +
                Story.get_cache(3).should.equal @feature
         | 
| 27 | 
            +
                Story.get_cache(4).should.equal @interview
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
              specify "should take on its parents cache options but be able to set its own" do
         | 
| 31 | 
            +
                @feature.cache_key.should.equal "Story:3"
         | 
| 32 | 
            +
                Feature.cache_config[:version] = 1
         | 
| 33 | 
            +
                @feature.cache_key.should.equal "Story:1:3"
         | 
| 34 | 
            +
                @story.cache_key.should.equal "Story:1"
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
            end
         | 
    
        metadata
    ADDED
    
    | @@ -0,0 +1,92 @@ | |
| 1 | 
            +
            --- !ruby/object:Gem::Specification 
         | 
| 2 | 
            +
            name: revo-cache_fu
         | 
| 3 | 
            +
            version: !ruby/object:Gem::Version 
         | 
| 4 | 
            +
              version: 1.0.0
         | 
| 5 | 
            +
            platform: ruby
         | 
| 6 | 
            +
            authors: 
         | 
| 7 | 
            +
            - Chris Wanstrath
         | 
| 8 | 
            +
            autorequire: 
         | 
| 9 | 
            +
            bindir: bin
         | 
| 10 | 
            +
            cert_chain: []
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            date: 2009-08-18 00:00:00 -07:00
         | 
| 13 | 
            +
            default_executable: 
         | 
| 14 | 
            +
            dependencies: []
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            description: DESCRIPTION!
         | 
| 17 | 
            +
            email: chris@ozmm.org
         | 
| 18 | 
            +
            executables: []
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            extensions: []
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            extra_rdoc_files: 
         | 
| 23 | 
            +
            - LICENSE
         | 
| 24 | 
            +
            - README
         | 
| 25 | 
            +
            files: 
         | 
| 26 | 
            +
            - CHANGELOG
         | 
| 27 | 
            +
            - LICENSE
         | 
| 28 | 
            +
            - README
         | 
| 29 | 
            +
            - Rakefile
         | 
| 30 | 
            +
            - VERSION
         | 
| 31 | 
            +
            - cache_fu.gemspec
         | 
| 32 | 
            +
            - defaults/extensions.rb.default
         | 
| 33 | 
            +
            - defaults/memcached.yml.default
         | 
| 34 | 
            +
            - defaults/memcached_ctl.default
         | 
| 35 | 
            +
            - init.rb
         | 
| 36 | 
            +
            - install.rb
         | 
| 37 | 
            +
            - lib/acts_as_cached.rb
         | 
| 38 | 
            +
            - lib/acts_as_cached/benchmarking.rb
         | 
| 39 | 
            +
            - lib/acts_as_cached/cache_methods.rb
         | 
| 40 | 
            +
            - lib/acts_as_cached/config.rb
         | 
| 41 | 
            +
            - lib/acts_as_cached/disabled.rb
         | 
| 42 | 
            +
            - lib/acts_as_cached/fragment_cache.rb
         | 
| 43 | 
            +
            - lib/acts_as_cached/local_cache.rb
         | 
| 44 | 
            +
            - lib/acts_as_cached/memcached_rails.rb
         | 
| 45 | 
            +
            - lib/acts_as_cached/recipes.rb
         | 
| 46 | 
            +
            - tasks/memcached.rake
         | 
| 47 | 
            +
            - test/benchmarking_test.rb
         | 
| 48 | 
            +
            - test/cache_test.rb
         | 
| 49 | 
            +
            - test/config_test.rb
         | 
| 50 | 
            +
            - test/disabled_test.rb
         | 
| 51 | 
            +
            - test/extensions_test.rb
         | 
| 52 | 
            +
            - test/fragment_cache_test.rb
         | 
| 53 | 
            +
            - test/helper.rb
         | 
| 54 | 
            +
            - test/local_cache_test.rb
         | 
| 55 | 
            +
            - test/sti_test.rb
         | 
| 56 | 
            +
            has_rdoc: false
         | 
| 57 | 
            +
            homepage: http://github.com/defunkt/cache_fu
         | 
| 58 | 
            +
            licenses: 
         | 
| 59 | 
            +
            post_install_message: 
         | 
| 60 | 
            +
            rdoc_options: 
         | 
| 61 | 
            +
            - --charset=UTF-8
         | 
| 62 | 
            +
            require_paths: 
         | 
| 63 | 
            +
            - lib
         | 
| 64 | 
            +
            required_ruby_version: !ruby/object:Gem::Requirement 
         | 
| 65 | 
            +
              requirements: 
         | 
| 66 | 
            +
              - - ">="
         | 
| 67 | 
            +
                - !ruby/object:Gem::Version 
         | 
| 68 | 
            +
                  version: "0"
         | 
| 69 | 
            +
              version: 
         | 
| 70 | 
            +
            required_rubygems_version: !ruby/object:Gem::Requirement 
         | 
| 71 | 
            +
              requirements: 
         | 
| 72 | 
            +
              - - ">="
         | 
| 73 | 
            +
                - !ruby/object:Gem::Version 
         | 
| 74 | 
            +
                  version: "0"
         | 
| 75 | 
            +
              version: 
         | 
| 76 | 
            +
            requirements: []
         | 
| 77 | 
            +
             | 
| 78 | 
            +
            rubyforge_project: 
         | 
| 79 | 
            +
            rubygems_version: 1.3.5
         | 
| 80 | 
            +
            signing_key: 
         | 
| 81 | 
            +
            specification_version: 3
         | 
| 82 | 
            +
            summary: Summarize your gem
         | 
| 83 | 
            +
            test_files: 
         | 
| 84 | 
            +
            - test/sti_test.rb
         | 
| 85 | 
            +
            - test/benchmarking_test.rb
         | 
| 86 | 
            +
            - test/local_cache_test.rb
         | 
| 87 | 
            +
            - test/config_test.rb
         | 
| 88 | 
            +
            - test/extensions_test.rb
         | 
| 89 | 
            +
            - test/fragment_cache_test.rb
         | 
| 90 | 
            +
            - test/disabled_test.rb
         | 
| 91 | 
            +
            - test/cache_test.rb
         | 
| 92 | 
            +
            - test/helper.rb
         |