viximo-cache-money 0.3.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/LICENSE +201 -0
 - data/README +204 -0
 - data/README.markdown +204 -0
 - data/TODO +17 -0
 - data/UNSUPPORTED_FEATURES +13 -0
 - data/config/environment.rb +8 -0
 - data/config/memcached.yml +4 -0
 - data/db/schema.rb +18 -0
 - data/init.rb +1 -0
 - data/lib/cache_money.rb +105 -0
 - data/lib/cash/accessor.rb +83 -0
 - data/lib/cash/adapter/memcache_client.rb +36 -0
 - data/lib/cash/adapter/memcached.rb +127 -0
 - data/lib/cash/adapter/redis.rb +144 -0
 - data/lib/cash/buffered.rb +137 -0
 - data/lib/cash/config.rb +78 -0
 - data/lib/cash/fake.rb +83 -0
 - data/lib/cash/finders.rb +50 -0
 - data/lib/cash/index.rb +211 -0
 - data/lib/cash/local.rb +105 -0
 - data/lib/cash/lock.rb +63 -0
 - data/lib/cash/mock.rb +158 -0
 - data/lib/cash/query/abstract.rb +219 -0
 - data/lib/cash/query/calculation.rb +45 -0
 - data/lib/cash/query/primary_key.rb +50 -0
 - data/lib/cash/query/select.rb +16 -0
 - data/lib/cash/request.rb +3 -0
 - data/lib/cash/transactional.rb +43 -0
 - data/lib/cash/util/array.rb +9 -0
 - data/lib/cash/util/marshal.rb +19 -0
 - data/lib/cash/version.rb +3 -0
 - data/lib/cash/write_through.rb +71 -0
 - data/lib/mem_cached_session_store.rb +49 -0
 - data/lib/mem_cached_support_store.rb +143 -0
 - data/rails/init.rb +1 -0
 - data/spec/cash/accessor_spec.rb +186 -0
 - data/spec/cash/active_record_spec.rb +224 -0
 - data/spec/cash/buffered_spec.rb +9 -0
 - data/spec/cash/calculations_spec.rb +78 -0
 - data/spec/cash/finders_spec.rb +455 -0
 - data/spec/cash/local_buffer_spec.rb +9 -0
 - data/spec/cash/local_spec.rb +9 -0
 - data/spec/cash/lock_spec.rb +110 -0
 - data/spec/cash/marshal_spec.rb +60 -0
 - data/spec/cash/order_spec.rb +172 -0
 - data/spec/cash/transactional_spec.rb +602 -0
 - data/spec/cash/window_spec.rb +195 -0
 - data/spec/cash/without_caching_spec.rb +32 -0
 - data/spec/cash/write_through_spec.rb +252 -0
 - data/spec/spec_helper.rb +87 -0
 - metadata +300 -0
 
    
        data/rails/init.rb
    ADDED
    
    | 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'cache_money'
         
     | 
| 
         @@ -0,0 +1,186 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "spec_helper"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'ruby-debug'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module Cash
         
     | 
| 
      
 5 
     | 
    
         
            +
              describe Accessor do
         
     | 
| 
      
 6 
     | 
    
         
            +
                describe '#fetch' do
         
     | 
| 
      
 7 
     | 
    
         
            +
                  describe '#fetch("...")' do
         
     | 
| 
      
 8 
     | 
    
         
            +
                    describe 'when there is a cache miss' do
         
     | 
| 
      
 9 
     | 
    
         
            +
                      it 'returns nil' do
         
     | 
| 
      
 10 
     | 
    
         
            +
                        Story.fetch("yabba").should be_nil
         
     | 
| 
      
 11 
     | 
    
         
            +
                      end
         
     | 
| 
      
 12 
     | 
    
         
            +
                    end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                    describe 'when there is a cache hit' do
         
     | 
| 
      
 15 
     | 
    
         
            +
                      it 'returns the value of the cache' do
         
     | 
| 
      
 16 
     | 
    
         
            +
                        Story.set("yabba", "dabba")
         
     | 
| 
      
 17 
     | 
    
         
            +
                        Story.fetch("yabba").should == "dabba"
         
     | 
| 
      
 18 
     | 
    
         
            +
                      end
         
     | 
| 
      
 19 
     | 
    
         
            +
                    end
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  describe '#fetch([...])', :shared => true do
         
     | 
| 
      
 23 
     | 
    
         
            +
                    describe '#fetch([])' do
         
     | 
| 
      
 24 
     | 
    
         
            +
                      it 'returns the empty hash' do
         
     | 
| 
      
 25 
     | 
    
         
            +
                        Story.fetch([]).should == {}
         
     | 
| 
      
 26 
     | 
    
         
            +
                      end
         
     | 
| 
      
 27 
     | 
    
         
            +
                    end
         
     | 
| 
      
 28 
     | 
    
         
            +
                    
         
     | 
| 
      
 29 
     | 
    
         
            +
                    describe 'when there is a total cache miss' do
         
     | 
| 
      
 30 
     | 
    
         
            +
                      it 'yields the keys to the block' do
         
     | 
| 
      
 31 
     | 
    
         
            +
                        Story.fetch(["yabba", "dabba"]) { |*missing_ids| ["doo", "doo"] }.should == {
         
     | 
| 
      
 32 
     | 
    
         
            +
                          "Story:1/yabba" => "doo",
         
     | 
| 
      
 33 
     | 
    
         
            +
                          "Story:1/dabba" => "doo"
         
     | 
| 
      
 34 
     | 
    
         
            +
                        }
         
     | 
| 
      
 35 
     | 
    
         
            +
                      end
         
     | 
| 
      
 36 
     | 
    
         
            +
                    end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                    describe 'when there is a partial cache miss' do
         
     | 
| 
      
 39 
     | 
    
         
            +
                      it 'yields just the missing ids to the block' do
         
     | 
| 
      
 40 
     | 
    
         
            +
                        Story.set("yabba", "dabba")
         
     | 
| 
      
 41 
     | 
    
         
            +
                        Story.fetch(["yabba", "dabba"]) { |*missing_ids| "doo" }.should == {
         
     | 
| 
      
 42 
     | 
    
         
            +
                          "Story:1/yabba" => "dabba",
         
     | 
| 
      
 43 
     | 
    
         
            +
                          "Story:1/dabba" => "doo"
         
     | 
| 
      
 44 
     | 
    
         
            +
                        }
         
     | 
| 
      
 45 
     | 
    
         
            +
                      end
         
     | 
| 
      
 46 
     | 
    
         
            +
                    end
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                describe '#get' do
         
     | 
| 
      
 51 
     | 
    
         
            +
                  describe '#get("...")' do
         
     | 
| 
      
 52 
     | 
    
         
            +
                    describe 'when there is a cache miss' do
         
     | 
| 
      
 53 
     | 
    
         
            +
                      it 'returns the value of the block' do
         
     | 
| 
      
 54 
     | 
    
         
            +
                        Story.get("yabba") { "dabba" }.should == "dabba"
         
     | 
| 
      
 55 
     | 
    
         
            +
                      end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                      it 'adds to the cache' do
         
     | 
| 
      
 58 
     | 
    
         
            +
                        Story.get("yabba") { "dabba" }
         
     | 
| 
      
 59 
     | 
    
         
            +
                        Story.get("yabba").should == "dabba"
         
     | 
| 
      
 60 
     | 
    
         
            +
                      end
         
     | 
| 
      
 61 
     | 
    
         
            +
                    end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                    describe 'when there is a cache hit' do
         
     | 
| 
      
 64 
     | 
    
         
            +
                      before do
         
     | 
| 
      
 65 
     | 
    
         
            +
                        Story.set("yabba", "dabba")
         
     | 
| 
      
 66 
     | 
    
         
            +
                      end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                      it 'returns the value of the cache' do
         
     | 
| 
      
 69 
     | 
    
         
            +
                        Story.get("yabba") { "doo" }.should == "dabba"
         
     | 
| 
      
 70 
     | 
    
         
            +
                      end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                      it 'does nothing to the cache' do
         
     | 
| 
      
 73 
     | 
    
         
            +
                        Story.get("yabba") { "doo" }
         
     | 
| 
      
 74 
     | 
    
         
            +
                        Story.get("yabba").should == "dabba"
         
     | 
| 
      
 75 
     | 
    
         
            +
                      end
         
     | 
| 
      
 76 
     | 
    
         
            +
                    end
         
     | 
| 
      
 77 
     | 
    
         
            +
                  end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                  describe '#get([...])' do
         
     | 
| 
      
 80 
     | 
    
         
            +
                    it_should_behave_like "#fetch([...])"
         
     | 
| 
      
 81 
     | 
    
         
            +
                  end
         
     | 
| 
      
 82 
     | 
    
         
            +
                end
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                describe '#add' do
         
     | 
| 
      
 85 
     | 
    
         
            +
                  describe 'when the value already exists' do
         
     | 
| 
      
 86 
     | 
    
         
            +
                    describe 'when a block is given' do
         
     | 
| 
      
 87 
     | 
    
         
            +
                      it 'yields to the block' do
         
     | 
| 
      
 88 
     | 
    
         
            +
                        Story.set("count", 1)
         
     | 
| 
      
 89 
     | 
    
         
            +
                        Story.add("count", 1) { "yield me" }.should == "yield me"
         
     | 
| 
      
 90 
     | 
    
         
            +
                      end
         
     | 
| 
      
 91 
     | 
    
         
            +
                    end
         
     | 
| 
      
 92 
     | 
    
         
            +
                    
         
     | 
| 
      
 93 
     | 
    
         
            +
                    describe 'when no block is given' do
         
     | 
| 
      
 94 
     | 
    
         
            +
                      it 'does not error' do
         
     | 
| 
      
 95 
     | 
    
         
            +
                        Story.set("count", 1)
         
     | 
| 
      
 96 
     | 
    
         
            +
                        lambda { Story.add("count", 1) }.should_not raise_error
         
     | 
| 
      
 97 
     | 
    
         
            +
                      end
         
     | 
| 
      
 98 
     | 
    
         
            +
                    end
         
     | 
| 
      
 99 
     | 
    
         
            +
                  end
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                  describe 'when the value does not already exist' do
         
     | 
| 
      
 102 
     | 
    
         
            +
                    it 'adds the key to the cache' do
         
     | 
| 
      
 103 
     | 
    
         
            +
                      Story.add("count", 1)
         
     | 
| 
      
 104 
     | 
    
         
            +
                      Story.get("count").should == 1
         
     | 
| 
      
 105 
     | 
    
         
            +
                    end
         
     | 
| 
      
 106 
     | 
    
         
            +
                  end
         
     | 
| 
      
 107 
     | 
    
         
            +
                end
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                describe '#set' do
         
     | 
| 
      
 110 
     | 
    
         
            +
                end
         
     | 
| 
      
 111 
     | 
    
         
            +
                
         
     | 
| 
      
 112 
     | 
    
         
            +
                describe '#incr' do
         
     | 
| 
      
 113 
     | 
    
         
            +
                  describe 'when there is a cache hit' do
         
     | 
| 
      
 114 
     | 
    
         
            +
                    before do
         
     | 
| 
      
 115 
     | 
    
         
            +
                      Story.set("count", 0, :raw => true)
         
     | 
| 
      
 116 
     | 
    
         
            +
                    end
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
                    it 'increments the value of the cache' do
         
     | 
| 
      
 119 
     | 
    
         
            +
                      Story.incr("count", 2)
         
     | 
| 
      
 120 
     | 
    
         
            +
                      Story.get("count", :raw => true).should =~ /2/
         
     | 
| 
      
 121 
     | 
    
         
            +
                    end
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
      
 123 
     | 
    
         
            +
                    it 'returns the new cache value' do
         
     | 
| 
      
 124 
     | 
    
         
            +
                      Story.incr("count", 2).should == 2
         
     | 
| 
      
 125 
     | 
    
         
            +
                    end
         
     | 
| 
      
 126 
     | 
    
         
            +
                  end
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
                  describe 'when there is a cache miss' do
         
     | 
| 
      
 129 
     | 
    
         
            +
                    it 'initializes the value of the cache to the value of the block' do
         
     | 
| 
      
 130 
     | 
    
         
            +
                      Story.incr("count", 1) { 5 }
         
     | 
| 
      
 131 
     | 
    
         
            +
                      Story.get("count", :raw => true).should =~ /5/
         
     | 
| 
      
 132 
     | 
    
         
            +
                    end
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
                    it 'returns the new cache value' do
         
     | 
| 
      
 135 
     | 
    
         
            +
                      Story.incr("count", 1) { 2 }.should == 2
         
     | 
| 
      
 136 
     | 
    
         
            +
                    end
         
     | 
| 
      
 137 
     | 
    
         
            +
                  end
         
     | 
| 
      
 138 
     | 
    
         
            +
                end
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
                describe '#decr' do
         
     | 
| 
      
 141 
     | 
    
         
            +
                  describe 'when there is a cache hit' do
         
     | 
| 
      
 142 
     | 
    
         
            +
                    before do
         
     | 
| 
      
 143 
     | 
    
         
            +
                      Story.incr("count", 1) { 10 }
         
     | 
| 
      
 144 
     | 
    
         
            +
                    end
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
                    it 'decrements the value of the cache' do
         
     | 
| 
      
 147 
     | 
    
         
            +
                      Story.decr("count", 2)
         
     | 
| 
      
 148 
     | 
    
         
            +
                      Story.get("count", :raw => true).should =~ /8/
         
     | 
| 
      
 149 
     | 
    
         
            +
                    end
         
     | 
| 
      
 150 
     | 
    
         
            +
             
     | 
| 
      
 151 
     | 
    
         
            +
                    it 'returns the new cache value' do
         
     | 
| 
      
 152 
     | 
    
         
            +
                      Story.decr("count", 2).should == 8
         
     | 
| 
      
 153 
     | 
    
         
            +
                    end
         
     | 
| 
      
 154 
     | 
    
         
            +
                  end
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
      
 156 
     | 
    
         
            +
                  describe 'when there is a cache miss' do
         
     | 
| 
      
 157 
     | 
    
         
            +
                    it 'initializes the value of the cache to the value of the block' do
         
     | 
| 
      
 158 
     | 
    
         
            +
                      Story.decr("count", 1) { 5 }
         
     | 
| 
      
 159 
     | 
    
         
            +
                      Story.get("count", :raw => true).should =~ /5/
         
     | 
| 
      
 160 
     | 
    
         
            +
                    end
         
     | 
| 
      
 161 
     | 
    
         
            +
             
     | 
| 
      
 162 
     | 
    
         
            +
                    it 'returns the new cache value' do
         
     | 
| 
      
 163 
     | 
    
         
            +
                      Story.decr("count", 1) { 2 }.should == 2
         
     | 
| 
      
 164 
     | 
    
         
            +
                    end
         
     | 
| 
      
 165 
     | 
    
         
            +
                  end
         
     | 
| 
      
 166 
     | 
    
         
            +
                end
         
     | 
| 
      
 167 
     | 
    
         
            +
             
     | 
| 
      
 168 
     | 
    
         
            +
                describe '#expire' do
         
     | 
| 
      
 169 
     | 
    
         
            +
                  it 'deletes the key' do
         
     | 
| 
      
 170 
     | 
    
         
            +
                    Story.set("bobo", 1)
         
     | 
| 
      
 171 
     | 
    
         
            +
                    Story.expire("bobo")
         
     | 
| 
      
 172 
     | 
    
         
            +
                    Story.get("bobo").should == nil
         
     | 
| 
      
 173 
     | 
    
         
            +
                  end
         
     | 
| 
      
 174 
     | 
    
         
            +
                end
         
     | 
| 
      
 175 
     | 
    
         
            +
                
         
     | 
| 
      
 176 
     | 
    
         
            +
                describe '#cache_key' do
         
     | 
| 
      
 177 
     | 
    
         
            +
                  it 'uses the version number' do
         
     | 
| 
      
 178 
     | 
    
         
            +
                    Story.version 1
         
     | 
| 
      
 179 
     | 
    
         
            +
                    Story.cache_key("foo").should == "Story:1/foo"
         
     | 
| 
      
 180 
     | 
    
         
            +
             
     | 
| 
      
 181 
     | 
    
         
            +
                    Story.version 2
         
     | 
| 
      
 182 
     | 
    
         
            +
                    Story.cache_key("foo").should == "Story:2/foo"
         
     | 
| 
      
 183 
     | 
    
         
            +
                  end
         
     | 
| 
      
 184 
     | 
    
         
            +
                end
         
     | 
| 
      
 185 
     | 
    
         
            +
              end
         
     | 
| 
      
 186 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,224 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "spec_helper"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Cash
         
     | 
| 
      
 4 
     | 
    
         
            +
              describe Finders do
         
     | 
| 
      
 5 
     | 
    
         
            +
                describe 'when the cache is populated' do
         
     | 
| 
      
 6 
     | 
    
         
            +
                  describe "#find" do
         
     | 
| 
      
 7 
     | 
    
         
            +
                    describe '#find(id...)' do
         
     | 
| 
      
 8 
     | 
    
         
            +
                      describe '#find(id)' do
         
     | 
| 
      
 9 
     | 
    
         
            +
                        it "returns an active record" do
         
     | 
| 
      
 10 
     | 
    
         
            +
                          story = Story.create!(:title => 'a story')
         
     | 
| 
      
 11 
     | 
    
         
            +
                          Story.find(story.id).should == story
         
     | 
| 
      
 12 
     | 
    
         
            +
                        end
         
     | 
| 
      
 13 
     | 
    
         
            +
                      end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                      describe 'when the object is destroyed' do
         
     | 
| 
      
 16 
     | 
    
         
            +
                        describe '#find(id)' do
         
     | 
| 
      
 17 
     | 
    
         
            +
                          it "raises an error" do
         
     | 
| 
      
 18 
     | 
    
         
            +
                            story = Story.create!(:title => "I am delicious")
         
     | 
| 
      
 19 
     | 
    
         
            +
                            story.destroy
         
     | 
| 
      
 20 
     | 
    
         
            +
                            lambda { Story.find(story.id) }.should raise_error(ActiveRecord::RecordNotFound)
         
     | 
| 
      
 21 
     | 
    
         
            +
                          end
         
     | 
| 
      
 22 
     | 
    
         
            +
                        end
         
     | 
| 
      
 23 
     | 
    
         
            +
                      end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                      describe '#find(id1, id2, ...)' do
         
     | 
| 
      
 26 
     | 
    
         
            +
                        it "returns an array" do
         
     | 
| 
      
 27 
     | 
    
         
            +
                          story1, story2 = Story.create!, Story.create!
         
     | 
| 
      
 28 
     | 
    
         
            +
                          Story.find(story1.id, story2.id).should == [story1, story2]
         
     | 
| 
      
 29 
     | 
    
         
            +
                        end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                        describe "#find(id, nil)" do
         
     | 
| 
      
 32 
     | 
    
         
            +
                          it "ignores the nils" do
         
     | 
| 
      
 33 
     | 
    
         
            +
                            story = Story.create!
         
     | 
| 
      
 34 
     | 
    
         
            +
                            Story.find(story.id, nil).should == story
         
     | 
| 
      
 35 
     | 
    
         
            +
                          end
         
     | 
| 
      
 36 
     | 
    
         
            +
                        end
         
     | 
| 
      
 37 
     | 
    
         
            +
                      end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                      describe 'when given nonexistent ids' do
         
     | 
| 
      
 40 
     | 
    
         
            +
                        describe 'when given one nonexistent id' do
         
     | 
| 
      
 41 
     | 
    
         
            +
                          it 'raises an error' do
         
     | 
| 
      
 42 
     | 
    
         
            +
                            lambda { Story.find(1) }.should raise_error(ActiveRecord::RecordNotFound)
         
     | 
| 
      
 43 
     | 
    
         
            +
                          end
         
     | 
| 
      
 44 
     | 
    
         
            +
                        end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                        describe 'when given multiple nonexistent ids' do
         
     | 
| 
      
 47 
     | 
    
         
            +
                           it "raises an error" do
         
     | 
| 
      
 48 
     | 
    
         
            +
                            lambda { Story.find(1, 2, 3) }.should raise_error(ActiveRecord::RecordNotFound)
         
     | 
| 
      
 49 
     | 
    
         
            +
                          end
         
     | 
| 
      
 50 
     | 
    
         
            +
                        end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                        describe '#find(nil)' do
         
     | 
| 
      
 54 
     | 
    
         
            +
                          it 'raises an error' do
         
     | 
| 
      
 55 
     | 
    
         
            +
                            lambda { Story.find(nil) }.should raise_error(ActiveRecord::RecordNotFound)
         
     | 
| 
      
 56 
     | 
    
         
            +
                          end
         
     | 
| 
      
 57 
     | 
    
         
            +
                        end
         
     | 
| 
      
 58 
     | 
    
         
            +
                      end
         
     | 
| 
      
 59 
     | 
    
         
            +
                    end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                    describe '#find(object)' do
         
     | 
| 
      
 62 
     | 
    
         
            +
                      it "coerces arguments to integers" do
         
     | 
| 
      
 63 
     | 
    
         
            +
                        story = Story.create!
         
     | 
| 
      
 64 
     | 
    
         
            +
                        Story.find(story.id.to_s).should == story
         
     | 
| 
      
 65 
     | 
    
         
            +
                      end
         
     | 
| 
      
 66 
     | 
    
         
            +
                    end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                    describe '#find([...])' do
         
     | 
| 
      
 69 
     | 
    
         
            +
                      describe 'when given an array with valid ids' do
         
     | 
| 
      
 70 
     | 
    
         
            +
                        it "#finds the object with that id" do
         
     | 
| 
      
 71 
     | 
    
         
            +
                          story = Story.create!
         
     | 
| 
      
 72 
     | 
    
         
            +
                          Story.find([story.id]).should == [story]
         
     | 
| 
      
 73 
     | 
    
         
            +
                        end
         
     | 
| 
      
 74 
     | 
    
         
            +
                      end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                      describe '#find([])' do
         
     | 
| 
      
 77 
     | 
    
         
            +
                        it 'returns the empty array' do
         
     | 
| 
      
 78 
     | 
    
         
            +
                          Story.find([]).should == []
         
     | 
| 
      
 79 
     | 
    
         
            +
                        end
         
     | 
| 
      
 80 
     | 
    
         
            +
                      end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                      describe 'when given nonexistent ids' do
         
     | 
| 
      
 83 
     | 
    
         
            +
                        it 'raises an error' do
         
     | 
| 
      
 84 
     | 
    
         
            +
                          lambda { Story.find([1, 2, 3]) }.should raise_error(ActiveRecord::RecordNotFound)
         
     | 
| 
      
 85 
     | 
    
         
            +
                        end
         
     | 
| 
      
 86 
     | 
    
         
            +
                      end
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                      describe 'when given limits and offsets' do
         
     | 
| 
      
 89 
     | 
    
         
            +
                        describe '#find([1, 2, ...], :limit => ..., :offset => ...)' do
         
     | 
| 
      
 90 
     | 
    
         
            +
                          it "returns the correct slice of objects" do
         
     | 
| 
      
 91 
     | 
    
         
            +
                            character1 = Character.create!(:name => "Sam", :story_id => 1)
         
     | 
| 
      
 92 
     | 
    
         
            +
                            character2 = Character.create!(:name => "Sam", :story_id => 1)
         
     | 
| 
      
 93 
     | 
    
         
            +
                            character3 = Character.create!(:name => "Sam", :story_id => 1)
         
     | 
| 
      
 94 
     | 
    
         
            +
                            Character.find(
         
     | 
| 
      
 95 
     | 
    
         
            +
                              [character1.id, character2.id, character3.id],
         
     | 
| 
      
 96 
     | 
    
         
            +
                              :conditions => { :name => "Sam", :story_id => 1 }, :limit => 2
         
     | 
| 
      
 97 
     | 
    
         
            +
                            ).should == [character1, character2]
         
     | 
| 
      
 98 
     | 
    
         
            +
                          end
         
     | 
| 
      
 99 
     | 
    
         
            +
                        end
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                        describe '#find([1], :limit => 0)' do
         
     | 
| 
      
 102 
     | 
    
         
            +
                          it "raises an error" do
         
     | 
| 
      
 103 
     | 
    
         
            +
                            character = Character.create!(:name => "Sam", :story_id => 1)
         
     | 
| 
      
 104 
     | 
    
         
            +
                            lambda do
         
     | 
| 
      
 105 
     | 
    
         
            +
                              Character.find([character.id], :conditions => { :name => "Sam", :story_id => 1 }, :limit => 0)
         
     | 
| 
      
 106 
     | 
    
         
            +
                            end.should raise_error(ActiveRecord::RecordNotFound)
         
     | 
| 
      
 107 
     | 
    
         
            +
                          end
         
     | 
| 
      
 108 
     | 
    
         
            +
                        end
         
     | 
| 
      
 109 
     | 
    
         
            +
                      end
         
     | 
| 
      
 110 
     | 
    
         
            +
                    end
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                    describe '#find(:first, ...)' do
         
     | 
| 
      
 113 
     | 
    
         
            +
                      describe '#find(:first, ..., :offset => ...)' do
         
     | 
| 
      
 114 
     | 
    
         
            +
                        it "#finds the object in the correct order" do
         
     | 
| 
      
 115 
     | 
    
         
            +
                          story1 = Story.create!(:title => 'title1')
         
     | 
| 
      
 116 
     | 
    
         
            +
                          story2 = Story.create!(:title => story1.title)
         
     | 
| 
      
 117 
     | 
    
         
            +
                          Story.find(:first, :conditions => { :title => story1.title }, :offset => 1).should == story2
         
     | 
| 
      
 118 
     | 
    
         
            +
                        end
         
     | 
| 
      
 119 
     | 
    
         
            +
                      end
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
                      describe '#find(:first, :conditions => [])' do
         
     | 
| 
      
 122 
     | 
    
         
            +
                        it 'finds the object in the correct order' do
         
     | 
| 
      
 123 
     | 
    
         
            +
                          story = Story.create!
         
     | 
| 
      
 124 
     | 
    
         
            +
                          Story.find(:first, :conditions => []).should == story
         
     | 
| 
      
 125 
     | 
    
         
            +
                        end
         
     | 
| 
      
 126 
     | 
    
         
            +
                      end
         
     | 
| 
      
 127 
     | 
    
         
            +
                    
         
     | 
| 
      
 128 
     | 
    
         
            +
                      describe "#find(:first, :conditions => '...')" do
         
     | 
| 
      
 129 
     | 
    
         
            +
                        it "coerces ruby values to the appropriate database values" do
         
     | 
| 
      
 130 
     | 
    
         
            +
                          story1 = Story.create! :title => 'a story', :published => true
         
     | 
| 
      
 131 
     | 
    
         
            +
                          story2 = Story.create! :title => 'another story', :published => false
         
     | 
| 
      
 132 
     | 
    
         
            +
                          Story.find(:first, :conditions => 'published = 0').should == story2
         
     | 
| 
      
 133 
     | 
    
         
            +
                        end
         
     | 
| 
      
 134 
     | 
    
         
            +
                      end
         
     | 
| 
      
 135 
     | 
    
         
            +
                    end
         
     | 
| 
      
 136 
     | 
    
         
            +
                  end
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
                  describe '#find_by_attr' do
         
     | 
| 
      
 139 
     | 
    
         
            +
                    describe '#find_by_attr(nil)' do
         
     | 
| 
      
 140 
     | 
    
         
            +
                      it 'returns nil' do
         
     | 
| 
      
 141 
     | 
    
         
            +
                        Story.find_by_id(nil).should == nil
         
     | 
| 
      
 142 
     | 
    
         
            +
                      end
         
     | 
| 
      
 143 
     | 
    
         
            +
                    end
         
     | 
| 
      
 144 
     | 
    
         
            +
             
     | 
| 
      
 145 
     | 
    
         
            +
                    describe 'when given non-existent ids' do
         
     | 
| 
      
 146 
     | 
    
         
            +
                      it 'returns nil' do
         
     | 
| 
      
 147 
     | 
    
         
            +
                        Story.find_by_id(-1).should == nil
         
     | 
| 
      
 148 
     | 
    
         
            +
                      end
         
     | 
| 
      
 149 
     | 
    
         
            +
                    end
         
     | 
| 
      
 150 
     | 
    
         
            +
                  end
         
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
      
 152 
     | 
    
         
            +
                  describe '#find_all_by_attr' do
         
     | 
| 
      
 153 
     | 
    
         
            +
                    describe 'when given non-existent ids' do
         
     | 
| 
      
 154 
     | 
    
         
            +
                      it "does not raise an error" do
         
     | 
| 
      
 155 
     | 
    
         
            +
                        lambda { Story.find_all_by_id([-1, -2, -3]) }.should_not raise_error
         
     | 
| 
      
 156 
     | 
    
         
            +
                      end
         
     | 
| 
      
 157 
     | 
    
         
            +
                    end
         
     | 
| 
      
 158 
     | 
    
         
            +
                  end
         
     | 
| 
      
 159 
     | 
    
         
            +
                end
         
     | 
| 
      
 160 
     | 
    
         
            +
             
     | 
| 
      
 161 
     | 
    
         
            +
                describe 'when the cache is partially populated' do
         
     | 
| 
      
 162 
     | 
    
         
            +
                  describe '#find(:all, :conditions => ...)' do
         
     | 
| 
      
 163 
     | 
    
         
            +
                    it "returns the correct records" do
         
     | 
| 
      
 164 
     | 
    
         
            +
                      story1 = Story.create!(:title => title = 'once upon a time...')
         
     | 
| 
      
 165 
     | 
    
         
            +
                      $memcache.flush_all
         
     | 
| 
      
 166 
     | 
    
         
            +
                      story2 = Story.create!(:title => title)
         
     | 
| 
      
 167 
     | 
    
         
            +
                      Story.find(:all, :conditions => { :title => story1.title }).should == [story1, story2]
         
     | 
| 
      
 168 
     | 
    
         
            +
                    end
         
     | 
| 
      
 169 
     | 
    
         
            +
                  end
         
     | 
| 
      
 170 
     | 
    
         
            +
             
     | 
| 
      
 171 
     | 
    
         
            +
                  describe '#find(id1, id2, ...)' do
         
     | 
| 
      
 172 
     | 
    
         
            +
                    it "returns the correct records" do
         
     | 
| 
      
 173 
     | 
    
         
            +
                      story1 = Story.create!(:title => 'story 1')
         
     | 
| 
      
 174 
     | 
    
         
            +
                      $memcache.flush_all
         
     | 
| 
      
 175 
     | 
    
         
            +
                      story2 = Story.create!(:title => 'story 2')
         
     | 
| 
      
 176 
     | 
    
         
            +
                      Story.find(story1.id, story2.id).should == [story1, story2]
         
     | 
| 
      
 177 
     | 
    
         
            +
                    end
         
     | 
| 
      
 178 
     | 
    
         
            +
                  end
         
     | 
| 
      
 179 
     | 
    
         
            +
                end
         
     | 
| 
      
 180 
     | 
    
         
            +
             
     | 
| 
      
 181 
     | 
    
         
            +
                describe 'when the cache is not populated' do
         
     | 
| 
      
 182 
     | 
    
         
            +
                  describe '#find(id)' do
         
     | 
| 
      
 183 
     | 
    
         
            +
                    it "returns the correct records" do
         
     | 
| 
      
 184 
     | 
    
         
            +
                      story = Story.create!(:title => 'a story')
         
     | 
| 
      
 185 
     | 
    
         
            +
                      $memcache.flush_all
         
     | 
| 
      
 186 
     | 
    
         
            +
                      Story.find(story.id).should == story
         
     | 
| 
      
 187 
     | 
    
         
            +
                    end
         
     | 
| 
      
 188 
     | 
    
         
            +
             
     | 
| 
      
 189 
     | 
    
         
            +
                    it "handles after_find on model" do
         
     | 
| 
      
 190 
     | 
    
         
            +
                      class AfterFindStory < Story
         
     | 
| 
      
 191 
     | 
    
         
            +
                        def after_find
         
     | 
| 
      
 192 
     | 
    
         
            +
                          self.title
         
     | 
| 
      
 193 
     | 
    
         
            +
                        end
         
     | 
| 
      
 194 
     | 
    
         
            +
                      end
         
     | 
| 
      
 195 
     | 
    
         
            +
                      lambda do
         
     | 
| 
      
 196 
     | 
    
         
            +
                        AfterFindStory.create!(:title => 'a story') 
         
     | 
| 
      
 197 
     | 
    
         
            +
                      end.should_not raise_error(ActiveRecord::MissingAttributeError)
         
     | 
| 
      
 198 
     | 
    
         
            +
                    end
         
     | 
| 
      
 199 
     | 
    
         
            +
                  end
         
     | 
| 
      
 200 
     | 
    
         
            +
             
     | 
| 
      
 201 
     | 
    
         
            +
                  describe '#find(id1, id2, ...)' do
         
     | 
| 
      
 202 
     | 
    
         
            +
                    it "handles finds with multiple ids correctly" do
         
     | 
| 
      
 203 
     | 
    
         
            +
                      story1 = Story.create!
         
     | 
| 
      
 204 
     | 
    
         
            +
                      story2 = Story.create!
         
     | 
| 
      
 205 
     | 
    
         
            +
                      $memcache.flush_all
         
     | 
| 
      
 206 
     | 
    
         
            +
                      Story.find(story1.id, story2.id).should == [story1, story2]
         
     | 
| 
      
 207 
     | 
    
         
            +
                    end
         
     | 
| 
      
 208 
     | 
    
         
            +
                  end
         
     | 
| 
      
 209 
     | 
    
         
            +
                end
         
     | 
| 
      
 210 
     | 
    
         
            +
                
         
     | 
| 
      
 211 
     | 
    
         
            +
                describe 'loading' do
         
     | 
| 
      
 212 
     | 
    
         
            +
                  it "should be able to create a record for an ar subclass that was loaded before cache money" do
         
     | 
| 
      
 213 
     | 
    
         
            +
                    $debug = true
         
     | 
| 
      
 214 
     | 
    
         
            +
                    session = ActiveRecord::SessionStore::Session.new
         
     | 
| 
      
 215 
     | 
    
         
            +
                    session.session_id = "12345"
         
     | 
| 
      
 216 
     | 
    
         
            +
                    session.data = "foobarbaz"
         
     | 
| 
      
 217 
     | 
    
         
            +
             
     | 
| 
      
 218 
     | 
    
         
            +
                    lambda {
         
     | 
| 
      
 219 
     | 
    
         
            +
                      session.save!
         
     | 
| 
      
 220 
     | 
    
         
            +
                    }.should_not raise_error
         
     | 
| 
      
 221 
     | 
    
         
            +
                  end
         
     | 
| 
      
 222 
     | 
    
         
            +
                end
         
     | 
| 
      
 223 
     | 
    
         
            +
              end
         
     | 
| 
      
 224 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,78 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "spec_helper"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Cash
         
     | 
| 
      
 4 
     | 
    
         
            +
              describe Finders do
         
     | 
| 
      
 5 
     | 
    
         
            +
                describe 'Calculations' do
         
     | 
| 
      
 6 
     | 
    
         
            +
                  describe 'when the cache is populated' do
         
     | 
| 
      
 7 
     | 
    
         
            +
                    before do
         
     | 
| 
      
 8 
     | 
    
         
            +
                      @stories = [Story.create!(:title => @title = 'asdf'), Story.create!(:title => @title)]
         
     | 
| 
      
 9 
     | 
    
         
            +
                    end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                    describe '#count(:all, :conditions => ...)' do
         
     | 
| 
      
 12 
     | 
    
         
            +
                      it "does not use the database" do
         
     | 
| 
      
 13 
     | 
    
         
            +
                        Story.count(:all, :conditions => { :title => @title }).should == @stories.size
         
     | 
| 
      
 14 
     | 
    
         
            +
                      end
         
     | 
| 
      
 15 
     | 
    
         
            +
                    end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                    describe '#count(:column, :conditions => ...)' do
         
     | 
| 
      
 18 
     | 
    
         
            +
                      it "uses the database, not the cache" do
         
     | 
| 
      
 19 
     | 
    
         
            +
                        mock(Story).get.never
         
     | 
| 
      
 20 
     | 
    
         
            +
                        Story.count(:title, :conditions => { :title => @title }).should == @stories.size
         
     | 
| 
      
 21 
     | 
    
         
            +
                      end
         
     | 
| 
      
 22 
     | 
    
         
            +
                    end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                    describe '#count(:all, :distinct => ..., :select => ...)' do
         
     | 
| 
      
 25 
     | 
    
         
            +
                      it 'uses the database, not the cache' do
         
     | 
| 
      
 26 
     | 
    
         
            +
                        mock(Story).get.never
         
     | 
| 
      
 27 
     | 
    
         
            +
                        Story.count(:all, :distinct => true, :select => :title, :conditions => { :title => @title }).should == @stories.collect(&:title).uniq.size
         
     | 
| 
      
 28 
     | 
    
         
            +
                      end
         
     | 
| 
      
 29 
     | 
    
         
            +
                    end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                    describe 'association proxies' do
         
     | 
| 
      
 32 
     | 
    
         
            +
                      describe '#count(:all, :conditions => ...)' do
         
     | 
| 
      
 33 
     | 
    
         
            +
                        it 'does not use the database' do
         
     | 
| 
      
 34 
     | 
    
         
            +
                          story = Story.create!
         
     | 
| 
      
 35 
     | 
    
         
            +
                          characters = [story.characters.create!(:name => name = 'name'), story.characters.create!(:name => name)]
         
     | 
| 
      
 36 
     | 
    
         
            +
                          mock(Story.connection).execute.never
         
     | 
| 
      
 37 
     | 
    
         
            +
                          story.characters.count(:all, :conditions => { :name => name }).should == characters.size
         
     | 
| 
      
 38 
     | 
    
         
            +
                        end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                        it 'has correct counter cache' do
         
     | 
| 
      
 41 
     | 
    
         
            +
                          story = Story.create!
         
     | 
| 
      
 42 
     | 
    
         
            +
                          characters = [story.characters.create!(:name => name = 'name'), story.characters.create!(:name => name)]
         
     | 
| 
      
 43 
     | 
    
         
            +
                          $memcache.flush_all
         
     | 
| 
      
 44 
     | 
    
         
            +
                          story.characters.find(:all, :conditions => { :name => name }) == characters
         
     | 
| 
      
 45 
     | 
    
         
            +
                          story.characters.count(:all, :conditions => { :name => name }).should == characters.size
         
     | 
| 
      
 46 
     | 
    
         
            +
                          story.characters.find(:all, :conditions => { :name => name }) == characters
         
     | 
| 
      
 47 
     | 
    
         
            +
                          mock(Story.connection).execute.never
         
     | 
| 
      
 48 
     | 
    
         
            +
                          story.characters.count(:all, :conditions => { :name => name }).should == characters.size
         
     | 
| 
      
 49 
     | 
    
         
            +
                        end
         
     | 
| 
      
 50 
     | 
    
         
            +
                      end
         
     | 
| 
      
 51 
     | 
    
         
            +
                    end
         
     | 
| 
      
 52 
     | 
    
         
            +
                  end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                  describe 'when the cache is not populated' do
         
     | 
| 
      
 55 
     | 
    
         
            +
                    describe '#count(:all, ...)' do
         
     | 
| 
      
 56 
     | 
    
         
            +
                      describe '#count(:all)' do
         
     | 
| 
      
 57 
     | 
    
         
            +
                        it 'uses the database, not the cache' do
         
     | 
| 
      
 58 
     | 
    
         
            +
                          mock(Story).get.never
         
     | 
| 
      
 59 
     | 
    
         
            +
                          Story.count
         
     | 
| 
      
 60 
     | 
    
         
            +
                        end
         
     | 
| 
      
 61 
     | 
    
         
            +
                      end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                      describe '#count(:all, :conditions => ...)' do
         
     | 
| 
      
 64 
     | 
    
         
            +
                        before do
         
     | 
| 
      
 65 
     | 
    
         
            +
                          Story.create!(:title => @title = 'title')
         
     | 
| 
      
 66 
     | 
    
         
            +
                          $memcache.flush_all
         
     | 
| 
      
 67 
     | 
    
         
            +
                        end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                        it "populates the count correctly" do
         
     | 
| 
      
 70 
     | 
    
         
            +
                          Story.count(:all, :conditions => { :title => @title }).should == 1
         
     | 
| 
      
 71 
     | 
    
         
            +
                          Story.fetch("title/#{@title}/count", :raw => true).should =~ /\s*1\s*/
         
     | 
| 
      
 72 
     | 
    
         
            +
                        end
         
     | 
| 
      
 73 
     | 
    
         
            +
                      end
         
     | 
| 
      
 74 
     | 
    
         
            +
                    end
         
     | 
| 
      
 75 
     | 
    
         
            +
                  end
         
     | 
| 
      
 76 
     | 
    
         
            +
                end
         
     | 
| 
      
 77 
     | 
    
         
            +
              end
         
     | 
| 
      
 78 
     | 
    
         
            +
            end
         
     |