From 2ffb585802d657c45b191ee5aaea5fad81aecda1 Mon Sep 17 00:00:00 2001 From: Doug Puchalski Date: Thu, 12 Jan 2012 11:36:44 -0800 Subject: [PATCH 1/4] Use rspec2 (~> 2.8) --- api_cache.gemspec | 2 +- spec/spec_helper.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/api_cache.gemspec b/api_cache.gemspec index 0076a5d..b2e1f26 100644 --- a/api_cache.gemspec +++ b/api_cache.gemspec @@ -16,7 +16,7 @@ Gem::Specification.new do |s| s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } s.require_paths = ["lib"] - s.add_development_dependency('rspec', "~> 1.0") + s.add_development_dependency('rspec', "~> 2.8") s.add_development_dependency('webmock') s.add_development_dependency('rake') s.add_development_dependency('moneta', "~> 0.6.0") diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index c1ec28e..7465bfa 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,4 +1,4 @@ -require "spec" +require "rspec" require 'webmock/rspec' $:.push File.join(File.dirname(__FILE__), '..', 'lib') From 371493e2e6bc340f59dc60d5cbfcc327fac3e1c4 Mon Sep 17 00:00:00 2001 From: Doug Puchalski Date: Thu, 12 Jan 2012 12:38:46 -0800 Subject: [PATCH 2/4] Add rspec ~> 2.7 to gemspec development dependencies --- api_cache.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api_cache.gemspec b/api_cache.gemspec index b2e1f26..1775101 100644 --- a/api_cache.gemspec +++ b/api_cache.gemspec @@ -16,7 +16,7 @@ Gem::Specification.new do |s| s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } s.require_paths = ["lib"] - s.add_development_dependency('rspec', "~> 2.8") + s.add_development_dependency('rspec', "~> 2.7") s.add_development_dependency('webmock') s.add_development_dependency('rake') s.add_development_dependency('moneta', "~> 0.6.0") From 33fd702b0edd629ff60e33b818b641b7790983fe Mon Sep 17 00:00:00 2001 From: Doug Puchalski Date: Thu, 12 Jan 2012 12:39:42 -0800 Subject: [PATCH 3/4] Check for initial :invalid state --- spec/cache_spec.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/spec/cache_spec.rb b/spec/cache_spec.rb index d194640..69af7aa 100644 --- a/spec/cache_spec.rb +++ b/spec/cache_spec.rb @@ -33,4 +33,10 @@ sleep 1 cache.state.should == :invalid end + + it "should initially have invalid state" do + cache = APICache::Cache.new('foo', @options) + cache.state.should == :invalid + end + end From bd8b6bbc5b5bd91a1dd5a4938fc97cb9938c5e65 Mon Sep 17 00:00:00 2001 From: Doug Puchalski Date: Thu, 12 Jan 2012 12:40:19 -0800 Subject: [PATCH 4/4] Add delete (expire) feature --- lib/api_cache.rb | 7 ++ lib/api_cache/abstract_store.rb | 5 ++ lib/api_cache/cache.rb | 4 + lib/api_cache/dalli_store.rb | 5 ++ lib/api_cache/memory_store.rb | 4 + lib/api_cache/moneta_store.rb | 5 ++ lib/api_cache/null_store.rb | 3 + spec/api_cache_spec.rb | 144 ++++++++++++++++++++------------ spec/dalli_store_spec.rb | 11 +++ spec/monteta_store_spec.rb | 11 +++ 10 files changed, 144 insertions(+), 55 deletions(-) diff --git a/lib/api_cache.rb b/lib/api_cache.rb index f063bcc..6224177 100644 --- a/lib/api_cache.rb +++ b/lib/api_cache.rb @@ -128,6 +128,13 @@ def self.get(key, options = {}, &block) end end end + + # Manually delete data from the cache. + # + def self.delete(key) + APICache::Cache.new(key, {}).delete + end + end require 'api_cache/cache' diff --git a/lib/api_cache/abstract_store.rb b/lib/api_cache/abstract_store.rb index 4f27926..339d580 100644 --- a/lib/api_cache/abstract_store.rb +++ b/lib/api_cache/abstract_store.rb @@ -14,6 +14,11 @@ def get(key) raise "Method not implemented. Called abstract class." end + # Delete value. + def delete(key) + raise "Method not implemented. Called abstract class." + end + # Does a given key exist in the cache? def exists?(key) raise "Method not implemented. Called abstract class." diff --git a/lib/api_cache/cache.rb b/lib/api_cache/cache.rb index b591eb8..5545975 100644 --- a/lib/api_cache/cache.rb +++ b/lib/api_cache/cache.rb @@ -47,6 +47,10 @@ def set(value) true end + def delete + store.delete(hash) + end + private def hash diff --git a/lib/api_cache/dalli_store.rb b/lib/api_cache/dalli_store.rb index 9546b43..a78ed88 100644 --- a/lib/api_cache/dalli_store.rb +++ b/lib/api_cache/dalli_store.rb @@ -16,6 +16,11 @@ def get(key) @dalli.get(key) end + # Delete value. + def delete(key) + @dalli.delete(key) + end + # Does a given key exist in the cache? def exists?(key) !get(key).nil? diff --git a/lib/api_cache/memory_store.rb b/lib/api_cache/memory_store.rb index 55217a2..ce7920c 100644 --- a/lib/api_cache/memory_store.rb +++ b/lib/api_cache/memory_store.rb @@ -18,6 +18,10 @@ def get(key) data end + def delete(key) + @cache.delete(key) + end + def exists?(key) !@cache[key].nil? end diff --git a/lib/api_cache/moneta_store.rb b/lib/api_cache/moneta_store.rb index 93015f4..1a6fa49 100644 --- a/lib/api_cache/moneta_store.rb +++ b/lib/api_cache/moneta_store.rb @@ -16,6 +16,11 @@ def get(key) @moneta[key] end + # Delete value. + def delete(key) + @moneta.delete(key) + end + # Does a given key exist in the cache? def exists?(key) @moneta.key?(key) diff --git a/lib/api_cache/null_store.rb b/lib/api_cache/null_store.rb index b2a0a41..ebd3c5b 100644 --- a/lib/api_cache/null_store.rb +++ b/lib/api_cache/null_store.rb @@ -13,6 +13,9 @@ def set(key, value) true end + def delete(key) + end + def expired?(key, timeout) true end diff --git a/spec/api_cache_spec.rb b/spec/api_cache_spec.rb index 7211011..a0cd551 100644 --- a/spec/api_cache_spec.rb +++ b/spec/api_cache_spec.rb @@ -40,62 +40,96 @@ end describe "get method" do - before :each do - @api = mock(APICache::API, :get => @api_data) - @cache = mock(APICache::Cache, :get => @cache_data, :set => true) - - APICache::API.stub!(:new).and_return(@api) - APICache::Cache.stub!(:new).and_return(@cache) - end - - it "should fetch data from the cache if the state is :current" do - @cache.stub!(:state).and_return(:current) - - APICache.get(@key).should == @cache_data - end - - it "should make new request to API if the state is :refetch and store result in cache" do - @cache.stub!(:state).and_return(:refetch) - @cache.should_receive(:set).with(@api_data) - - APICache.get(@key).should == @api_data - end - - it "should return the cached value if the state is :refetch but the api is not accessible" do - @cache.stub!(:state).and_return(:refetch) - @api.should_receive(:get).with.and_raise(APICache::CannotFetch) - - APICache.get(@key).should == @cache_data - end - - it "should make new request to API if the state is :invalid" do - @cache.stub!(:state).and_return(:invalid) - - APICache.get(@key).should == @api_data - end - - it "should raise CannotFetch if the api cannot fetch data and the cache state is :invalid" do - @cache.stub!(:state).and_return(:invalid) - @api.should_receive(:get).with.and_raise(APICache::CannotFetch) - - lambda { - APICache.get(@key).should - }.should raise_error(APICache::CannotFetch) - end - - it "should make new request to API if the state is :missing" do - @cache.stub!(:state).and_return(:missing) - - APICache.get(@key).should == @api_data + + context "when cache is mocked" do + before :each do + @api = mock(APICache::API, :get => @api_data) + @cache = mock(APICache::Cache, :get => @cache_data, :set => true) + + APICache::API.stub!(:new).and_return(@api) + APICache::Cache.stub!(:new).and_return(@cache) + end + + it "should fetch data from the cache if the state is :current" do + @cache.stub!(:state).and_return(:current) + + APICache.get(@key).should == @cache_data + end + + it "should make new request to API if the state is :refetch and store result in cache" do + @cache.stub!(:state).and_return(:refetch) + @cache.should_receive(:set).with(@api_data) + + APICache.get(@key).should == @api_data + end + + it "should return the cached value if the state is :refetch but the api is not accessible" do + @cache.stub!(:state).and_return(:refetch) + @api.should_receive(:get).with.and_raise(APICache::CannotFetch) + + APICache.get(@key).should == @cache_data + end + + it "should make new request to API if the state is :invalid" do + @cache.stub!(:state).and_return(:invalid) + + APICache.get(@key).should == @api_data + end + + it "should raise CannotFetch if the api cannot fetch data and the cache state is :invalid" do + @cache.stub!(:state).and_return(:invalid) + @api.should_receive(:get).with.and_raise(APICache::CannotFetch) + + lambda { + APICache.get(@key).should + }.should raise_error(APICache::CannotFetch) + end + + it "should make new request to API if the state is :missing" do + @cache.stub!(:state).and_return(:missing) + + APICache.get(@key).should == @api_data + end + + it "should raise an exception if the api cannot fetch data and the cache state is :missing" do + @cache.stub!(:state).and_return(:missing) + @api.should_receive(:get).with.and_raise(APICache::CannotFetch) + + lambda { + APICache.get(@key).should + }.should raise_error(APICache::CannotFetch) + end end - - it "should raise an exception if the api cannot fetch data and the cache state is :missing" do - @cache.stub!(:state).and_return(:missing) - @api.should_receive(:get).with.and_raise(APICache::CannotFetch) - - lambda { - APICache.get(@key).should - }.should raise_error(APICache::CannotFetch) + + + context "when cache is not mocked" do + + before :each do + APICache.store = APICache::MemoryStore.new + @api = mock(APICache::API, :get => @api_data) + APICache::API.stub!(:new).and_return(@api) + end + + #it "should initially fetch" do + # @api.should_receive(:get) + # APICache.get(@key) + #end + + it "should only fetch once" do + @api.should_receive(:get).once + APICache.get(@key) + APICache.get(@key) + end + + it "should refetch if deleted" do + @api.should_receive(:get).twice + APICache.get(@key) + APICache.delete(@key) + APICache.get(@key) + end + end + end + end diff --git a/spec/dalli_store_spec.rb b/spec/dalli_store_spec.rb index 4fc1b46..048eda0 100644 --- a/spec/dalli_store_spec.rb +++ b/spec/dalli_store_spec.rb @@ -27,4 +27,15 @@ sleep 1 @store.expired?('foo', 1).should be_true end + + context "after delete" do + + it "should no longer exist" do + @store.set("key", "value") + @store.delete("key") + @store.exists?("key").should be_false + end + + end + end diff --git a/spec/monteta_store_spec.rb b/spec/monteta_store_spec.rb index 2d14318..b49995f 100644 --- a/spec/monteta_store_spec.rb +++ b/spec/monteta_store_spec.rb @@ -28,4 +28,15 @@ sleep 1 @store.expired?('foo', 1).should be_true end + + context "after delete" do + + it "should no longer exist" do + @store.set("key", "value") + @store.delete("key") + @store.exists?("key").should be_false + end + + end + end