api_cache 0.2.3 → 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 04d4fca20574868e21c48d50e07ae2d6cc78f493
4
+ data.tar.gz: a8b1f69f0a0fe9d9c5ee30a6fa5becffe3bcb4e7
5
+ SHA512:
6
+ metadata.gz: 9df4d242de81e51b02398ca4781a18ae83460e3b059f14410d438334423928a533c7025fea819258d5a3fc1338b928ef3085092826cc6ea521b47d9645fc8189
7
+ data.tar.gz: 23e2d15510a671df5f6ca4d488890165785cce3df10ab67b12b4502d0f85bb456d17c9e706c717c3ae7db47226b4e9f4f726231c296c95ded2baab99a16b27d4
@@ -0,0 +1,7 @@
1
+ # Changelog
2
+
3
+ ## 0.3.0 – 2014-07-16
4
+
5
+ * [NEW] Allow keys to be deleted [Doug Puchalski]
6
+ * [UPDATED] Updated Moneta dependency - works with 0.7.x & 0.8.x
7
+ * [FIX] Fixed long standing bug in the case that the `created_at` key was evicted before the data key (for example when using memcached)
data/README.md CHANGED
@@ -16,8 +16,7 @@ APICache allows any API client library to be easily wrapped with a robust cachin
16
16
 
17
17
  # Use a proper store
18
18
  require 'moneta'
19
- require 'moneta/memcache'
20
- APICache.store = Moneta::Memcache.new(:server => "localhost")
19
+ APICache.store = Moneta.new(:Memcached)
21
20
 
22
21
  # Wrap an API, and handle the failure case
23
22
 
@@ -94,8 +93,7 @@ You can send any of the following options to `APICache.get(url, options = {}, &b
94
93
 
95
94
  Before using the APICache you should set the cache to use. By default an in memory hash is used - obviously not a great idea. Thankfully APICache can use any moneta store, so for example if you wanted to use memcache you'd do this:
96
95
 
97
- require 'moneta/memcache'
98
- APICache.store = Moneta::Memcache.new(:server => "localhost")
96
+ APICache.store = Moneta.new(:Memcached)
99
97
 
100
98
  Please be liberal with the github issue tracker, more so with pull requests, or drop me a mail to me [at] mloughran [dot] com. I'd love to hear from you.
101
99
 
data/Rakefile CHANGED
@@ -1,10 +1,7 @@
1
1
  require 'bundler'
2
2
  Bundler::GemHelper.install_tasks
3
3
 
4
- require 'spec/rake/spectask'
5
- Spec::Rake::SpecTask.new(:spec) do |t|
6
- t.libs << 'lib' << 'spec'
7
- t.spec_files = FileList['spec/**/*_spec.rb']
8
- end
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new
9
6
 
10
7
  task :default => :spec
@@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__)
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "api_cache"
6
- s.version = "0.2.3"
6
+ s.version = "0.3.0"
7
7
  s.platform = Gem::Platform::RUBY
8
8
  s.authors = ["Martyn Loughran"]
9
9
  s.email = ["me@mloughran.com"]
@@ -16,10 +16,9 @@ Gem::Specification.new do |s|
16
16
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
17
  s.require_paths = ["lib"]
18
18
 
19
- s.add_development_dependency('rspec', "~> 1.0")
19
+ s.add_development_dependency('rspec', "~> 2.7")
20
20
  s.add_development_dependency('webmock')
21
21
  s.add_development_dependency('rake')
22
- s.add_development_dependency('moneta', "~> 0.6.0")
22
+ s.add_development_dependency('moneta', "~> 0.7")
23
23
  s.add_development_dependency('dalli')
24
- s.add_development_dependency('memcache-client')
25
24
  end
@@ -128,6 +128,13 @@ class APICache
128
128
  end
129
129
  end
130
130
  end
131
+
132
+ # Manually delete data from the cache.
133
+ #
134
+ def self.delete(key)
135
+ APICache::Cache.new(key, {}).delete
136
+ end
137
+
131
138
  end
132
139
 
133
140
  require 'api_cache/cache'
@@ -14,14 +14,30 @@ class APICache
14
14
  raise "Method not implemented. Called abstract class."
15
15
  end
16
16
 
17
+ # Delete the given key. The return value is not used.
18
+ def delete(key)
19
+ raise "Method not implemented. Called abstract class."
20
+ end
21
+
17
22
  # Does a given key exist in the cache?
18
23
  def exists?(key)
19
24
  raise "Method not implemented. Called abstract class."
20
25
  end
21
26
 
22
- # Has a given time passed since the key was set?
23
- def expired?(key, timeout)
27
+ # created_at returns the time when the key was last set
28
+ def created_at(key)
24
29
  raise "Method not implemented. Called abstract class."
25
30
  end
31
+
32
+ # expired? returns true if the given timeout has passed since the key was
33
+ # set. It has nothing to say about the existence or otherwise of said key.
34
+ def expired?(key, timeout)
35
+ if (created_at = created_at(key))
36
+ Time.now - created_at > timeout
37
+ else
38
+ # If the created_at data is missing assume expired
39
+ true
40
+ end
41
+ end
26
42
  end
27
43
  end
@@ -47,6 +47,11 @@ class APICache
47
47
  true
48
48
  end
49
49
 
50
+ def delete
51
+ store.delete(hash)
52
+ return nil
53
+ end
54
+
50
55
  private
51
56
 
52
57
  def hash
@@ -16,14 +16,18 @@ class APICache
16
16
  @dalli.get(key)
17
17
  end
18
18
 
19
+ # Delete value.
20
+ def delete(key)
21
+ @dalli.delete(key)
22
+ end
23
+
19
24
  # Does a given key exist in the cache?
20
25
  def exists?(key)
21
26
  !get(key).nil?
22
27
  end
23
28
 
24
- # Has a given time passed since the key was set?
25
- def expired?(key, timeout)
26
- Time.now - @dalli.get("#{key}_created_at") > timeout
29
+ def created_at(key)
30
+ @dalli.get("#{key}_created_at")
27
31
  end
28
32
  end
29
33
  end
@@ -1,8 +1,8 @@
1
1
  class APICache
2
2
  class MemoryStore < APICache::AbstractStore
3
- def initialize
3
+ def initialize(cache = {})
4
4
  APICache.logger.debug "Using memory store"
5
- @cache = {}
5
+ @cache = cache
6
6
  true
7
7
  end
8
8
 
@@ -13,23 +13,21 @@ class APICache
13
13
  end
14
14
 
15
15
  def get(key)
16
- data = @cache[key][1]
16
+ data = exists?(key) ? @cache[key][1] : nil
17
17
  APICache.logger.debug("cache: #{data.nil? ? "miss" : "hit"} (#{key})")
18
18
  data
19
19
  end
20
20
 
21
- def exists?(key)
22
- !@cache[key].nil?
21
+ def delete(key)
22
+ @cache.delete(key)
23
23
  end
24
24
 
25
- def expired?(key, timeout)
26
- Time.now - created(key) > timeout
25
+ def exists?(key)
26
+ !@cache[key].nil?
27
27
  end
28
28
 
29
- private
30
-
31
- def created(key)
32
- @cache[key][0]
29
+ def created_at(key)
30
+ @cache[key] && @cache[key][0]
33
31
  end
34
32
  end
35
33
  end
@@ -16,14 +16,18 @@ class APICache
16
16
  @moneta[key]
17
17
  end
18
18
 
19
+ # Delete value.
20
+ def delete(key)
21
+ @moneta.delete(key)
22
+ end
23
+
19
24
  # Does a given key exist in the cache?
20
25
  def exists?(key)
21
26
  @moneta.key?(key)
22
27
  end
23
28
 
24
- # Has a given time passed since the key was set?
25
- def expired?(key, timeout)
26
- Time.now - @moneta["#{key}_created_at"] > timeout
29
+ def created_at(key)
30
+ @moneta["#{key}_created_at"]
27
31
  end
28
32
  end
29
33
  end
@@ -4,17 +4,24 @@ class APICache
4
4
  class NullStore < APICache::AbstractStore
5
5
  def initialize
6
6
  end
7
-
8
- def exists?(key)
9
- false
10
- end
11
7
 
12
8
  def set(key, value)
13
9
  true
14
10
  end
15
11
 
16
- def expired?(key, timeout)
17
- true
12
+ def get(key)
13
+ nil
14
+ end
15
+
16
+ def delete(key)
17
+ end
18
+
19
+ def exists?(key)
20
+ false
21
+ end
22
+
23
+ def created_at(key)
24
+ nil
18
25
  end
19
26
  end
20
27
  end
@@ -23,8 +23,7 @@ describe APICache do
23
23
 
24
24
  it "should allow moneta instances to be passed" do
25
25
  require 'moneta'
26
- require 'moneta/memory'
27
- APICache.store = Moneta::Memory.new
26
+ APICache.store = Moneta.new(:Memory)
28
27
  APICache.store.should be_kind_of(APICache::MonetaStore)
29
28
  end
30
29
 
@@ -40,62 +39,96 @@ describe APICache do
40
39
  end
41
40
 
42
41
  describe "get method" do
43
- before :each do
44
- @api = mock(APICache::API, :get => @api_data)
45
- @cache = mock(APICache::Cache, :get => @cache_data, :set => true)
46
-
47
- APICache::API.stub!(:new).and_return(@api)
48
- APICache::Cache.stub!(:new).and_return(@cache)
49
- end
50
-
51
- it "should fetch data from the cache if the state is :current" do
52
- @cache.stub!(:state).and_return(:current)
53
-
54
- APICache.get(@key).should == @cache_data
55
- end
56
-
57
- it "should make new request to API if the state is :refetch and store result in cache" do
58
- @cache.stub!(:state).and_return(:refetch)
59
- @cache.should_receive(:set).with(@api_data)
60
-
61
- APICache.get(@key).should == @api_data
62
- end
63
-
64
- it "should return the cached value if the state is :refetch but the api is not accessible" do
65
- @cache.stub!(:state).and_return(:refetch)
66
- @api.should_receive(:get).with.and_raise(APICache::CannotFetch)
67
-
68
- APICache.get(@key).should == @cache_data
69
- end
70
-
71
- it "should make new request to API if the state is :invalid" do
72
- @cache.stub!(:state).and_return(:invalid)
73
-
74
- APICache.get(@key).should == @api_data
75
- end
76
-
77
- it "should raise CannotFetch if the api cannot fetch data and the cache state is :invalid" do
78
- @cache.stub!(:state).and_return(:invalid)
79
- @api.should_receive(:get).with.and_raise(APICache::CannotFetch)
80
-
81
- lambda {
82
- APICache.get(@key).should
83
- }.should raise_error(APICache::CannotFetch)
84
- end
85
-
86
- it "should make new request to API if the state is :missing" do
87
- @cache.stub!(:state).and_return(:missing)
88
-
89
- APICache.get(@key).should == @api_data
42
+
43
+ context "when cache is mocked" do
44
+ before :each do
45
+ @api = mock(APICache::API, :get => @api_data)
46
+ @cache = mock(APICache::Cache, :get => @cache_data, :set => true)
47
+
48
+ APICache::API.stub!(:new).and_return(@api)
49
+ APICache::Cache.stub!(:new).and_return(@cache)
50
+ end
51
+
52
+ it "should fetch data from the cache if the state is :current" do
53
+ @cache.stub!(:state).and_return(:current)
54
+
55
+ APICache.get(@key).should == @cache_data
56
+ end
57
+
58
+ it "should make new request to API if the state is :refetch and store result in cache" do
59
+ @cache.stub!(:state).and_return(:refetch)
60
+ @cache.should_receive(:set).with(@api_data)
61
+
62
+ APICache.get(@key).should == @api_data
63
+ end
64
+
65
+ it "should return the cached value if the state is :refetch but the api is not accessible" do
66
+ @cache.stub!(:state).and_return(:refetch)
67
+ @api.should_receive(:get).with.and_raise(APICache::CannotFetch)
68
+
69
+ APICache.get(@key).should == @cache_data
70
+ end
71
+
72
+ it "should make new request to API if the state is :invalid" do
73
+ @cache.stub!(:state).and_return(:invalid)
74
+
75
+ APICache.get(@key).should == @api_data
76
+ end
77
+
78
+ it "should raise CannotFetch if the api cannot fetch data and the cache state is :invalid" do
79
+ @cache.stub!(:state).and_return(:invalid)
80
+ @api.should_receive(:get).with.and_raise(APICache::CannotFetch)
81
+
82
+ lambda {
83
+ APICache.get(@key).should
84
+ }.should raise_error(APICache::CannotFetch)
85
+ end
86
+
87
+ it "should make new request to API if the state is :missing" do
88
+ @cache.stub!(:state).and_return(:missing)
89
+
90
+ APICache.get(@key).should == @api_data
91
+ end
92
+
93
+ it "should raise an exception if the api cannot fetch data and the cache state is :missing" do
94
+ @cache.stub!(:state).and_return(:missing)
95
+ @api.should_receive(:get).with.and_raise(APICache::CannotFetch)
96
+
97
+ lambda {
98
+ APICache.get(@key).should
99
+ }.should raise_error(APICache::CannotFetch)
100
+ end
90
101
  end
91
-
92
- it "should raise an exception if the api cannot fetch data and the cache state is :missing" do
93
- @cache.stub!(:state).and_return(:missing)
94
- @api.should_receive(:get).with.and_raise(APICache::CannotFetch)
95
-
96
- lambda {
97
- APICache.get(@key).should
98
- }.should raise_error(APICache::CannotFetch)
102
+
103
+
104
+ context "when cache is not mocked" do
105
+
106
+ before :each do
107
+ APICache.store = APICache::MemoryStore.new
108
+ @api = mock(APICache::API, :get => @api_data)
109
+ APICache::API.stub!(:new).and_return(@api)
110
+ end
111
+
112
+ #it "should initially fetch" do
113
+ # @api.should_receive(:get)
114
+ # APICache.get(@key)
115
+ #end
116
+
117
+ it "should only fetch once" do
118
+ @api.should_receive(:get).once
119
+ APICache.get(@key)
120
+ APICache.get(@key)
121
+ end
122
+
123
+ it "should refetch if deleted" do
124
+ @api.should_receive(:get).twice
125
+ APICache.get(@key)
126
+ APICache.delete(@key)
127
+ APICache.get(@key)
128
+ end
129
+
99
130
  end
131
+
100
132
  end
133
+
101
134
  end
@@ -33,4 +33,10 @@ describe APICache::Cache do
33
33
  sleep 1
34
34
  cache.state.should == :invalid
35
35
  end
36
+
37
+ it "should initially have invalid state" do
38
+ cache = APICache::Cache.new('foo', @options)
39
+ cache.state.should == :invalid
40
+ end
41
+
36
42
  end
@@ -3,28 +3,8 @@ require 'spec_helper'
3
3
  require 'dalli'
4
4
 
5
5
  describe APICache::DalliStore do
6
- before :each do
7
- @dalli = Dalli::Client.new('localhost:11211')
8
- @dalli.delete('foo')
9
- @store = APICache::DalliStore.new(@dalli)
10
- end
6
+ let(:cache) { Dalli::Client.new("localhost:11211") }
7
+ let(:store) { APICache::DalliStore.new(cache) }
11
8
 
12
- it 'should set and get' do
13
- @store.set('key', 'value')
14
- @store.get('key').should == 'value'
15
- end
16
-
17
- it 'should allow checking whether a key exists' do
18
- @store.exists?('foo').should be_false
19
- @store.set('foo', 'bar')
20
- @store.exists?('foo').should be_true
21
- end
22
-
23
- it 'should allow checking whether a given amount of time has passed since the key was set' do
24
- @store.expired?('foo', 1).should be_false
25
- @store.set('foo', 'bar')
26
- @store.expired?('foo', 1).should be_false
27
- sleep 1
28
- @store.expired?('foo', 1).should be_true
29
- end
9
+ include_examples "generic store"
30
10
  end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe APICache::MemoryStore do
4
+ let(:cache) { {} }
5
+ let(:store) { APICache::MemoryStore.new(cache) }
6
+
7
+ # Deleting created_at makes no sense given the way MemoryStore stores data
8
+ @skip_created_at_deletion = true
9
+ include_examples "generic store"
10
+ end
@@ -1,31 +1,10 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  require 'moneta'
4
- require 'moneta/memcache'
5
4
 
6
5
  describe APICache::MonetaStore do
7
- before :each do
8
- @moneta = Moneta::Memcache.new(:server => "localhost")
9
- @moneta.delete('foo')
10
- @store = APICache::MonetaStore.new(@moneta)
11
- end
6
+ let(:cache) { Moneta.new(:Memcached) }
7
+ let(:store) { APICache::MonetaStore.new(cache) }
12
8
 
13
- it "should set and get" do
14
- @store.set("key", "value")
15
- @store.get("key").should == "value"
16
- end
17
-
18
- it "should allow checking whether a key exists" do
19
- @store.exists?('foo').should be_false
20
- @store.set('foo', 'bar')
21
- @store.exists?('foo').should be_true
22
- end
23
-
24
- it "should allow checking whether a given amount of time has passed since the key was set" do
25
- @store.expired?('foo', 1).should be_false
26
- @store.set('foo', 'bar')
27
- @store.expired?('foo', 1).should be_false
28
- sleep 1
29
- @store.expired?('foo', 1).should be_true
30
- end
9
+ include_examples "generic store"
31
10
  end
@@ -11,7 +11,7 @@ describe APICache::NullStore do
11
11
  @store.exists?('foo').should be_false
12
12
  end
13
13
 
14
- it "should allows say keys are expired" do
14
+ it "should always say keys are expired" do
15
15
  @store.expired?('foo', 1).should be_true
16
16
  @store.set('foo', 'bar')
17
17
  @store.expired?('foo', 1).should be_true
@@ -0,0 +1,42 @@
1
+ shared_examples "generic store" do
2
+ before :each do
3
+ cache.delete("foo")
4
+ end
5
+
6
+ it "should allow set and get" do
7
+ store.set("foo", "bar")
8
+ store.get("foo").should == "bar"
9
+ end
10
+
11
+ it "should report existence" do
12
+ store.exists?("foo").should == false
13
+ store.set("foo", "bar")
14
+ store.exists?("foo").should == true
15
+ end
16
+
17
+ it "should allow checking expiration" do
18
+ store.set("foo", "bar")
19
+ store.expired?("foo", 1).should == false
20
+ store.expired?("foo", 0).should == true
21
+ end
22
+
23
+ it "should return nil if not found" do
24
+ store.get("nothing").should == nil
25
+ end
26
+
27
+ it "should be possible to delete" do
28
+ store.set("foo", "bar")
29
+ store.delete("key")
30
+ store.exists?("key").should == false
31
+ store.get("key").should == nil
32
+ end
33
+
34
+ unless @skip_created_at_deletion
35
+ it "should claim that key has expired if _created_at key is missing" do
36
+ store.set("key", "bar")
37
+ store.expired?("foo", 10).should == false
38
+ cache.delete("foo_created_at")
39
+ store.expired?("foo", 10).should == true
40
+ end
41
+ end
42
+ end
@@ -1,7 +1,9 @@
1
- require "spec"
1
+ require "rspec"
2
2
  require 'webmock/rspec'
3
3
 
4
4
  $:.push File.join(File.dirname(__FILE__), '..', 'lib')
5
5
  require "api_cache"
6
6
 
7
7
  APICache.logger.level = Logger::FATAL
8
+
9
+ require "shared_store_specs"
metadata CHANGED
@@ -1,95 +1,97 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: api_cache
3
- version: !ruby/object:Gem::Version
4
- prerelease:
5
- version: 0.2.3
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
6
5
  platform: ruby
7
- authors:
6
+ authors:
8
7
  - Martyn Loughran
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
-
13
- date: 2011-03-28 00:00:00 +01:00
14
- default_executable:
15
- dependencies:
16
- - !ruby/object:Gem::Dependency
11
+ date: 2014-07-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
17
14
  name: rspec
18
- prerelease: false
19
- requirement: &id001 !ruby/object:Gem::Requirement
20
- none: false
21
- requirements:
22
- - - ~>
23
- - !ruby/object:Gem::Version
24
- version: "1.0"
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.7'
25
20
  type: :development
26
- version_requirements: *id001
27
- - !ruby/object:Gem::Dependency
28
- name: webmock
29
21
  prerelease: false
30
- requirement: &id002 !ruby/object:Gem::Requirement
31
- none: false
32
- requirements:
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: webmock
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
33
31
  - - ">="
34
- - !ruby/object:Gem::Version
35
- version: "0"
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
36
34
  type: :development
37
- version_requirements: *id002
38
- - !ruby/object:Gem::Dependency
39
- name: rake
40
35
  prerelease: false
41
- requirement: &id003 !ruby/object:Gem::Requirement
42
- none: false
43
- requirements:
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
44
45
  - - ">="
45
- - !ruby/object:Gem::Version
46
- version: "0"
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
47
48
  type: :development
48
- version_requirements: *id003
49
- - !ruby/object:Gem::Dependency
50
- name: moneta
51
49
  prerelease: false
52
- requirement: &id004 !ruby/object:Gem::Requirement
53
- none: false
54
- requirements:
55
- - - ~>
56
- - !ruby/object:Gem::Version
57
- version: 0.6.0
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: moneta
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.7'
58
62
  type: :development
59
- version_requirements: *id004
60
- - !ruby/object:Gem::Dependency
61
- name: dalli
62
63
  prerelease: false
63
- requirement: &id005 !ruby/object:Gem::Requirement
64
- none: false
65
- requirements:
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.7'
69
+ - !ruby/object:Gem::Dependency
70
+ name: dalli
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
66
73
  - - ">="
67
- - !ruby/object:Gem::Version
68
- version: "0"
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
69
76
  type: :development
70
- version_requirements: *id005
71
- - !ruby/object:Gem::Dependency
72
- name: memcache-client
73
77
  prerelease: false
74
- requirement: &id006 !ruby/object:Gem::Requirement
75
- none: false
76
- requirements:
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
77
80
  - - ">="
78
- - !ruby/object:Gem::Version
79
- version: "0"
80
- type: :development
81
- version_requirements: *id006
82
- description: APICache allows any API client library to be easily wrapped with a robust caching layer. It supports caching (obviously), serving stale data and limits on the number of API calls. It's also got a handy syntax if all you want to do is cache a bothersome url.
83
- email:
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: APICache allows any API client library to be easily wrapped with a robust
84
+ caching layer. It supports caching (obviously), serving stale data and limits on
85
+ the number of API calls. It's also got a handy syntax if all you want to do is cache
86
+ a bothersome url.
87
+ email:
84
88
  - me@mloughran.com
85
89
  executables: []
86
-
87
90
  extensions: []
88
-
89
91
  extra_rdoc_files: []
90
-
91
- files:
92
- - .gitignore
92
+ files:
93
+ - ".gitignore"
94
+ - CHANGELOG.md
93
95
  - Gemfile
94
96
  - LICENSE
95
97
  - README.md
@@ -110,43 +112,42 @@ files:
110
112
  - spec/cache_spec.rb
111
113
  - spec/dalli_store_spec.rb
112
114
  - spec/integration_spec.rb
115
+ - spec/memory_store_spec.rb
113
116
  - spec/monteta_store_spec.rb
114
117
  - spec/null_store_spec.rb
118
+ - spec/shared_store_specs.rb
115
119
  - spec/spec_helper.rb
116
- has_rdoc: true
117
120
  homepage: http://mloughran.github.com/api_cache/
118
121
  licenses: []
119
-
122
+ metadata: {}
120
123
  post_install_message:
121
124
  rdoc_options: []
122
-
123
- require_paths:
125
+ require_paths:
124
126
  - lib
125
- required_ruby_version: !ruby/object:Gem::Requirement
126
- none: false
127
- requirements:
127
+ required_ruby_version: !ruby/object:Gem::Requirement
128
+ requirements:
128
129
  - - ">="
129
- - !ruby/object:Gem::Version
130
- version: "0"
131
- required_rubygems_version: !ruby/object:Gem::Requirement
132
- none: false
133
- requirements:
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ required_rubygems_version: !ruby/object:Gem::Requirement
133
+ requirements:
134
134
  - - ">="
135
- - !ruby/object:Gem::Version
136
- version: "0"
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
137
  requirements: []
138
-
139
138
  rubyforge_project:
140
- rubygems_version: 1.5.3
139
+ rubygems_version: 2.2.2
141
140
  signing_key:
142
- specification_version: 3
141
+ specification_version: 4
143
142
  summary: API Cache allows advanced caching of APIs
144
- test_files:
143
+ test_files:
145
144
  - spec/api_cache_spec.rb
146
145
  - spec/api_spec.rb
147
146
  - spec/cache_spec.rb
148
147
  - spec/dalli_store_spec.rb
149
148
  - spec/integration_spec.rb
149
+ - spec/memory_store_spec.rb
150
150
  - spec/monteta_store_spec.rb
151
151
  - spec/null_store_spec.rb
152
+ - spec/shared_store_specs.rb
152
153
  - spec/spec_helper.rb