cachy 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +4 -4
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/cachy.gemspec +7 -8
- data/lib/cachy.rb +46 -8
- data/spec/cachy_spec.rb +126 -26
- metadata +14 -8
- data/rdoc/README.rdoc +0 -1
data/README.markdown
CHANGED
@@ -71,12 +71,15 @@ When they are updated the cache is automatically expired.
|
|
71
71
|
Use a global `CACHE_VERSION=1` so that all caches can be expired when something big changes.
|
72
72
|
The cache server does not need to be restarted and session data(Rails) is saved.
|
73
73
|
|
74
|
-
|
75
74
|
#### Does not cache nil
|
76
75
|
If you want to cache a falsy result, use false (same goes for :while_running)
|
77
76
|
Cachy.cache(:x){ expensive || false }
|
78
77
|
Cachy.cache(:x, :while_running=>false){ expensive }
|
79
78
|
|
79
|
+
###Cachy.cache_if
|
80
|
+
Only caches if condition is fulfilled
|
81
|
+
Cachy.cache_if(condition, :foo, 'bar', :expires_in => 1.minute){do_something}
|
82
|
+
|
80
83
|
###Cachy.expire / .expire_view
|
81
84
|
Expires all locales of a key
|
82
85
|
Cachy.locales = [:de, :en] # by default filled with I18n.available_locales
|
@@ -86,20 +89,17 @@ Expires all locales of a key
|
|
86
89
|
Cachy.expire_view(:my_key)
|
87
90
|
Cachy.expire(:my_key, :prefix=>'views/')
|
88
91
|
|
89
|
-
|
90
92
|
###Cachy.key
|
91
93
|
Use to cache e.g. Erb output
|
92
94
|
<% cache Cachy.key(:a_key), :expires_in=>1.hour do %>
|
93
95
|
More html ...
|
94
96
|
<% end %>
|
95
97
|
|
96
|
-
|
97
98
|
###Cachy.cache_store
|
98
99
|
No ActionController::Base.cache_store ?
|
99
100
|
Give me something that responds to read/write(Rails style) or []/store([Moneta](http://github.com/wycats/moneta/tree/master)) or get/set(Memcached)
|
100
101
|
Cachy.cache_store = some_cache
|
101
102
|
|
102
|
-
|
103
103
|
###Cachy.locales
|
104
104
|
No I18n.available_locales ?
|
105
105
|
Cachy.locales = [:de, :en, :fr]
|
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.4
|
data/cachy.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{cachy}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.4"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Michael Grosser"]
|
12
|
-
s.date = %q{
|
12
|
+
s.date = %q{2010-08-14}
|
13
13
|
s.email = %q{grosser.michael@gmail.com}
|
14
14
|
s.extra_rdoc_files = [
|
15
15
|
"README.markdown"
|
@@ -23,7 +23,6 @@ Gem::Specification.new do |s|
|
|
23
23
|
"lib/cachy/memcached_wrapper.rb",
|
24
24
|
"lib/cachy/moneta_wrapper.rb",
|
25
25
|
"lib/cachy/wrapper.rb",
|
26
|
-
"rdoc/README.rdoc",
|
27
26
|
"spec/cachy/memcached_wrapper_spec.rb",
|
28
27
|
"spec/cachy/moneta_wrapper_spec.rb",
|
29
28
|
"spec/cachy_spec.rb",
|
@@ -33,14 +32,14 @@ Gem::Specification.new do |s|
|
|
33
32
|
s.homepage = %q{http://github.com/grosser/cachy}
|
34
33
|
s.rdoc_options = ["--charset=UTF-8"]
|
35
34
|
s.require_paths = ["lib"]
|
36
|
-
s.rubygems_version = %q{1.3.
|
35
|
+
s.rubygems_version = %q{1.3.6}
|
37
36
|
s.summary = %q{Caching library for projects that have many processes or many caches}
|
38
37
|
s.test_files = [
|
39
|
-
"spec/
|
40
|
-
"spec/test_cache.rb",
|
41
|
-
"spec/cachy/memcached_wrapper_spec.rb",
|
38
|
+
"spec/cachy/memcached_wrapper_spec.rb",
|
42
39
|
"spec/cachy/moneta_wrapper_spec.rb",
|
43
|
-
"spec/cachy_spec.rb"
|
40
|
+
"spec/cachy_spec.rb",
|
41
|
+
"spec/test_cache.rb",
|
42
|
+
"spec/spec_helper.rb"
|
44
43
|
]
|
45
44
|
|
46
45
|
if s.respond_to? :specification_version then
|
data/lib/cachy.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
class Cachy
|
2
2
|
WHILE_RUNNING_TMEOUT = 5*60 #seconds
|
3
3
|
KEY_VERSION_TIMEOUT = 30 #seconds
|
4
|
+
HEALTH_CHECK_KEY = 'cachy_healthy'
|
5
|
+
KEY_VERSIONS_KEY = 'cachy_key_versions'
|
6
|
+
|
7
|
+
@@cache_error = false
|
4
8
|
|
5
9
|
# Cache the result of a block
|
6
10
|
#
|
@@ -13,7 +17,6 @@ class Cachy
|
|
13
17
|
key = key(*args)
|
14
18
|
options = extract_options!(args)
|
15
19
|
|
16
|
-
# Cached result?
|
17
20
|
result = cache_store.read(key)
|
18
21
|
return result unless result == nil
|
19
22
|
|
@@ -24,6 +27,14 @@ class Cachy
|
|
24
27
|
cache_store.write key, result, options
|
25
28
|
result
|
26
29
|
end
|
30
|
+
|
31
|
+
def self.cache_if(cond, *args, &block)
|
32
|
+
if cond
|
33
|
+
cache(*args, &block)
|
34
|
+
else
|
35
|
+
block.call
|
36
|
+
end
|
37
|
+
end
|
27
38
|
|
28
39
|
# Constructs a cache-key (first argument must be a String/Symbol)
|
29
40
|
#
|
@@ -43,7 +54,7 @@ class Cachy
|
|
43
54
|
end * "_"
|
44
55
|
|
45
56
|
key = (options[:hash_key] || hash_keys) ? hash(key) : key
|
46
|
-
options[:prefix].to_s + key + options[:suffix].to_s
|
57
|
+
(options[:prefix].to_s + key + options[:suffix].to_s).gsub(' ', '_')
|
47
58
|
end
|
48
59
|
|
49
60
|
# Expire all possible locales of a cache, use the same arguments as with cache
|
@@ -72,7 +83,7 @@ class Cachy
|
|
72
83
|
@@key_versions = {:versions=>{}, :last_set=>0}
|
73
84
|
def self.key_versions
|
74
85
|
if key_versions_expired?
|
75
|
-
versions =
|
86
|
+
versions = read_versions
|
76
87
|
@@key_versions = {:versions=>versions, :last_set=>Time.now.to_i}
|
77
88
|
end
|
78
89
|
@@key_versions[:versions]
|
@@ -80,22 +91,29 @@ class Cachy
|
|
80
91
|
|
81
92
|
def self.key_versions=(data)
|
82
93
|
@@key_versions[:last_set] = 0 #expire current key
|
83
|
-
|
94
|
+
write_version(data)
|
84
95
|
end
|
85
96
|
|
86
97
|
# Expires all caches that use this key
|
87
98
|
def self.increment_key(key)
|
88
99
|
key = key.to_sym
|
89
|
-
|
100
|
+
current_versions = read_versions
|
101
|
+
version = current_versions[key] || 0
|
90
102
|
version += 1
|
91
|
-
self.key_versions =
|
103
|
+
self.key_versions = current_versions.merge(key => version)
|
92
104
|
version
|
93
105
|
end
|
94
106
|
|
107
|
+
def self.delete_key(key)
|
108
|
+
versions = key_versions.dup
|
109
|
+
versions.delete(key.to_sym)
|
110
|
+
self.key_versions = versions
|
111
|
+
end
|
112
|
+
|
95
113
|
class << self
|
96
114
|
attr_accessor :hash_keys
|
97
115
|
end
|
98
|
-
|
116
|
+
|
99
117
|
# Wrap non ActiveSupport style cache stores,
|
100
118
|
# to get the same interface for all
|
101
119
|
def self.cache_store=(x)
|
@@ -110,6 +128,7 @@ class Cachy
|
|
110
128
|
else
|
111
129
|
raise "This cache_store type is not usable for Cachy!"
|
112
130
|
end
|
131
|
+
@cache_store.write HEALTH_CHECK_KEY, 'yes'
|
113
132
|
end
|
114
133
|
|
115
134
|
def self.cache_store
|
@@ -135,6 +154,25 @@ class Cachy
|
|
135
154
|
|
136
155
|
private
|
137
156
|
|
157
|
+
def self.read_versions
|
158
|
+
data = cache_store.instance_variable_get('@data')
|
159
|
+
if data.respond_to? :read_error_occured # its a MemCache with read_error detection !
|
160
|
+
result = data[KEY_VERSIONS_KEY] || {}
|
161
|
+
@@cache_error = data.read_error_occured
|
162
|
+
result
|
163
|
+
else
|
164
|
+
cache_store.read(KEY_VERSIONS_KEY) || {}
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def self.write_version(data)
|
169
|
+
cache_store.write(KEY_VERSIONS_KEY, data) unless @@cache_error
|
170
|
+
end
|
171
|
+
|
172
|
+
def self.cache_healthy?
|
173
|
+
cache_store.read(HEALTH_CHECK_KEY) == 'yes'
|
174
|
+
end
|
175
|
+
|
138
176
|
# Do we need to fetch fresh key_versions from cache ?
|
139
177
|
def self.key_versions_expired?
|
140
178
|
key_versions_timeout = Time.now.to_i - KEY_VERSION_TIMEOUT
|
@@ -167,7 +205,7 @@ class Cachy
|
|
167
205
|
|
168
206
|
def self.key_version_for(key)
|
169
207
|
key = key.to_sym
|
170
|
-
key_versions[key] || increment_key(key)
|
208
|
+
key_versions[key] || (cache_healthy? ? increment_key(key) : 1)
|
171
209
|
end
|
172
210
|
|
173
211
|
def self.ensure_valid_keys(options)
|
data/spec/cachy_spec.rb
CHANGED
@@ -1,27 +1,25 @@
|
|
1
1
|
require 'spec/spec_helper'
|
2
2
|
|
3
|
-
TEST_CACHE = TestCache.new
|
4
|
-
|
5
3
|
describe Cachy do
|
6
|
-
before :all do
|
7
|
-
Cachy.cache_store = TEST_CACHE
|
8
|
-
end
|
9
|
-
|
10
4
|
before do
|
11
|
-
|
5
|
+
@cache = TestCache.new
|
6
|
+
Cachy.cache_store = @cache
|
7
|
+
Cachy.class_eval "@@key_versions = {:versions=>{}, :last_set=>0}"
|
8
|
+
@cache.write(Cachy::HEALTH_CHECK_KEY, 'yes')
|
9
|
+
Cachy.send(:class_variable_set, '@@cache_error', false)
|
12
10
|
end
|
13
|
-
|
11
|
+
|
14
12
|
describe :cache do
|
15
13
|
it "caches" do
|
16
14
|
Cachy.cache(:my_key){ "X" }.should == "X"
|
17
15
|
Cachy.cache(:my_key){ "ABC" }.should == "X"
|
18
16
|
end
|
19
|
-
|
17
|
+
|
20
18
|
it "expires" do
|
21
19
|
Cachy.cache(:his_key, :expires_in=> -100){ 'X' }.should == 'X'
|
22
20
|
Cachy.cache(:his_key, :expires_in=> -100){ 'X' }.should == 'X'
|
23
21
|
end
|
24
|
-
|
22
|
+
|
25
23
|
it "sets cache to intermediate value while running expensive query" do
|
26
24
|
Cachy.cache(:my_key, :while_running=>'A') do
|
27
25
|
Cachy.cache(:my_key){ 'X' }.should == 'A'
|
@@ -51,6 +49,29 @@ describe Cachy do
|
|
51
49
|
Cachy.cache(:x){ true }.should == true
|
52
50
|
end
|
53
51
|
end
|
52
|
+
|
53
|
+
describe :cache_if do
|
54
|
+
it "should not call the cache command if condition is wrong" do
|
55
|
+
Cachy.should_not_receive(:cache)
|
56
|
+
Cachy.cache_if(false, :x) do
|
57
|
+
"asd"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should call cache command if condition is true" do
|
62
|
+
Cachy.should_receive(:cache)
|
63
|
+
Cachy.cache_if(true, :x) do
|
64
|
+
"asd"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should pass params correctly" do
|
69
|
+
Cachy.should_receive(:cache).with(:x, {:y => 1}, :expires_in => 3)
|
70
|
+
Cachy.cache_if(true, :x, {:y => 1}, :expires_in => 3) do
|
71
|
+
"asd"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
54
75
|
|
55
76
|
describe :expire do
|
56
77
|
it "expires the cache for all languages" do
|
@@ -62,10 +83,10 @@ describe Cachy do
|
|
62
83
|
Cachy.cache(:my_key){ l }
|
63
84
|
end
|
64
85
|
|
65
|
-
|
86
|
+
@cache.keys.select{|k| k=~ /my_key/}.size.should == 4
|
66
87
|
Cachy.stub!(:locales).and_return locales
|
67
88
|
Cachy.expire(:my_key)
|
68
|
-
|
89
|
+
@cache.keys.select{|k| k=~ /my_key/}.size.should == 0
|
69
90
|
end
|
70
91
|
|
71
92
|
it "does not expire other keys" do
|
@@ -73,35 +94,35 @@ describe Cachy do
|
|
73
94
|
Cachy.cache(:my_key){ 'X' }
|
74
95
|
Cachy.cache(:yet_another_key){ 'X' }
|
75
96
|
Cachy.expire :my_key
|
76
|
-
|
77
|
-
|
97
|
+
@cache.keys.should include("another_key_v1")
|
98
|
+
@cache.keys.should include("yet_another_key_v1")
|
78
99
|
end
|
79
100
|
|
80
101
|
it "expires the cache when no available_locales are set" do
|
81
102
|
Cachy.cache(:another_key){ "X" }
|
82
103
|
Cachy.cache(:my_key){ "X" }
|
83
104
|
|
84
|
-
|
105
|
+
@cache.keys.select{|k| k=~ /my_key/}.size.should == 1
|
85
106
|
Cachy.expire(:my_key)
|
86
|
-
|
107
|
+
@cache.keys.select{|k| k=~ /my_key/}.size.should == 0
|
87
108
|
end
|
88
109
|
|
89
110
|
it "expires the cache with prefix" do
|
90
111
|
key = 'views/my_key_v1'
|
91
|
-
|
92
|
-
|
112
|
+
@cache.write(key, 'x')
|
113
|
+
@cache.read(key).should_not == nil
|
93
114
|
Cachy.expire(:my_key, :prefix=>'views/')
|
94
|
-
|
115
|
+
@cache.read(key).should == nil
|
95
116
|
end
|
96
117
|
end
|
97
118
|
|
98
119
|
describe :expire_view do
|
99
120
|
it "expires the cache with prefix" do
|
100
121
|
key = 'views/my_key_v1'
|
101
|
-
|
102
|
-
|
122
|
+
@cache.write(key, 'x')
|
123
|
+
@cache.read(key).should_not == nil
|
103
124
|
Cachy.expire_view(:my_key)
|
104
|
-
|
125
|
+
@cache.read(key).should == nil
|
105
126
|
end
|
106
127
|
end
|
107
128
|
|
@@ -121,11 +142,15 @@ describe Cachy do
|
|
121
142
|
end
|
122
143
|
|
123
144
|
it "gets the locale from I18n" do
|
124
|
-
module I18n
|
145
|
+
# a bit weird but just module I18n does not work with 1.9.1
|
146
|
+
i18n = Module.new
|
147
|
+
i18n.class_eval do
|
125
148
|
def self.locale
|
126
149
|
:de
|
127
150
|
end
|
128
151
|
end
|
152
|
+
Object.const_set :I18n, i18n
|
153
|
+
|
129
154
|
key = Cachy.key(:x)
|
130
155
|
Object.send :remove_const, :I18n #cleanup
|
131
156
|
key.should == "x_v1_de"
|
@@ -205,13 +230,24 @@ describe Cachy do
|
|
205
230
|
|
206
231
|
describe :key_versions do
|
207
232
|
before do
|
208
|
-
Cachy.key_versions =
|
233
|
+
Cachy.key_versions = nil
|
209
234
|
Cachy.key_versions.should == {}
|
210
235
|
end
|
211
236
|
|
237
|
+
it "merges in old when setting new" do
|
238
|
+
pending '!!!!!'
|
239
|
+
end
|
240
|
+
|
212
241
|
it "adds a key when cache is called the first time" do
|
213
242
|
Cachy.cache(:xxx){1}
|
214
243
|
Cachy.key_versions[:xxx].should == 1
|
244
|
+
@cache.read(Cachy::KEY_VERSIONS_KEY).should_not == nil
|
245
|
+
end
|
246
|
+
|
247
|
+
it "does not add a key when cache is called the first time and cache is not healthy" do
|
248
|
+
@cache.write(Cachy::HEALTH_CHECK_KEY, 'no')
|
249
|
+
Cachy.cache(:xxx){1}
|
250
|
+
@cache.read(Cachy::KEY_VERSIONS_KEY).should == nil
|
215
251
|
end
|
216
252
|
|
217
253
|
it "adds a string key as symbol" do
|
@@ -228,13 +264,13 @@ describe Cachy do
|
|
228
264
|
|
229
265
|
it "reloads when keys have expired" do
|
230
266
|
Cachy.send :class_variable_set, "@@key_versions", {:versions=>{:xx=>2}, :last_set=>(Time.now.to_i - 60)}
|
231
|
-
|
267
|
+
@cache.write Cachy::KEY_VERSIONS_KEY, {:xx=>1}
|
232
268
|
Cachy.key_versions.should == {:xx=>1}
|
233
269
|
end
|
234
270
|
|
235
271
|
it "does not reload when keys have not expired" do
|
236
272
|
Cachy.send :class_variable_set, "@@key_versions", {:versions=>{:xx=>2}, :last_set=>Time.now.to_i}
|
237
|
-
|
273
|
+
@cache.write Cachy::KEY_VERSIONS_KEY, {:xx=>1}
|
238
274
|
Cachy.key_versions.should == {:xx=>2}
|
239
275
|
end
|
240
276
|
|
@@ -244,4 +280,68 @@ describe Cachy do
|
|
244
280
|
Cachy.key_versions[:xx].should == 1
|
245
281
|
end
|
246
282
|
end
|
283
|
+
|
284
|
+
describe :key_versions, "with timeout" do
|
285
|
+
before do
|
286
|
+
@mock = mock = {}
|
287
|
+
@cache.instance_eval{@data = mock}
|
288
|
+
def @mock.read_error_occured
|
289
|
+
false
|
290
|
+
end
|
291
|
+
def @mock.[](x)
|
292
|
+
{:x => 1}
|
293
|
+
end
|
294
|
+
Cachy.send(:class_variable_set, '@@cache_error', false)
|
295
|
+
end
|
296
|
+
|
297
|
+
it "reads normally" do
|
298
|
+
Cachy.send(:read_versions).should == {:x => 1}
|
299
|
+
end
|
300
|
+
|
301
|
+
it "reads empty when it crashes" do
|
302
|
+
@mock.should_receive(:[]).and_return nil # e.g. Timout happended
|
303
|
+
@mock.should_receive(:read_error_occured).and_return true
|
304
|
+
Cachy.send(:read_versions).should == {}
|
305
|
+
end
|
306
|
+
|
307
|
+
it "marks as error when it crashes" do
|
308
|
+
Cachy.send(:class_variable_get, '@@cache_error').should == false
|
309
|
+
@mock.should_receive(:read_error_occured).and_return true
|
310
|
+
Cachy.send(:read_versions)
|
311
|
+
Cachy.send(:class_variable_get, '@@cache_error').should == true
|
312
|
+
end
|
313
|
+
|
314
|
+
it "marks as error free when it reads successfully" do
|
315
|
+
Cachy.send(:class_variable_set, '@@cache_error', true)
|
316
|
+
Cachy.send(:class_variable_get, '@@cache_error').should == true
|
317
|
+
Cachy.send(:read_versions).should == {:x => 1}
|
318
|
+
Cachy.send(:class_variable_get, '@@cache_error').should == false
|
319
|
+
end
|
320
|
+
|
321
|
+
it "writes when it was not error before" do
|
322
|
+
Cachy.cache_store.should_receive(:write)
|
323
|
+
Cachy.send(:write_version, {})
|
324
|
+
end
|
325
|
+
|
326
|
+
it "does not write when it was error before" do
|
327
|
+
Cachy.send(:class_variable_set, '@@cache_error', true)
|
328
|
+
Cachy.cache_store.should_not_receive(:write)
|
329
|
+
Cachy.send(:write_version, {})
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
describe :delete_key do
|
334
|
+
it "removes a key from key versions" do
|
335
|
+
Cachy.cache(:xxx){1}
|
336
|
+
Cachy.key_versions.key?(:xxx).should == true
|
337
|
+
Cachy.delete_key :xxx
|
338
|
+
Cachy.key_versions.key?(:xxx).should == false
|
339
|
+
end
|
340
|
+
|
341
|
+
it "does not crash with unfound key" do
|
342
|
+
Cachy.delete_key :xxx
|
343
|
+
Cachy.delete_key :xxx
|
344
|
+
Cachy.key_versions.key?(:xxx).should == false
|
345
|
+
end
|
346
|
+
end
|
247
347
|
end
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cachy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 4
|
9
|
+
version: 0.1.4
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Michael Grosser
|
@@ -9,7 +14,7 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date:
|
17
|
+
date: 2010-08-14 00:00:00 +02:00
|
13
18
|
default_executable:
|
14
19
|
dependencies: []
|
15
20
|
|
@@ -30,7 +35,6 @@ files:
|
|
30
35
|
- lib/cachy/memcached_wrapper.rb
|
31
36
|
- lib/cachy/moneta_wrapper.rb
|
32
37
|
- lib/cachy/wrapper.rb
|
33
|
-
- rdoc/README.rdoc
|
34
38
|
- spec/cachy/memcached_wrapper_spec.rb
|
35
39
|
- spec/cachy/moneta_wrapper_spec.rb
|
36
40
|
- spec/cachy_spec.rb
|
@@ -49,24 +53,26 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
49
53
|
requirements:
|
50
54
|
- - ">="
|
51
55
|
- !ruby/object:Gem::Version
|
56
|
+
segments:
|
57
|
+
- 0
|
52
58
|
version: "0"
|
53
|
-
version:
|
54
59
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
60
|
requirements:
|
56
61
|
- - ">="
|
57
62
|
- !ruby/object:Gem::Version
|
63
|
+
segments:
|
64
|
+
- 0
|
58
65
|
version: "0"
|
59
|
-
version:
|
60
66
|
requirements: []
|
61
67
|
|
62
68
|
rubyforge_project:
|
63
|
-
rubygems_version: 1.3.
|
69
|
+
rubygems_version: 1.3.6
|
64
70
|
signing_key:
|
65
71
|
specification_version: 3
|
66
72
|
summary: Caching library for projects that have many processes or many caches
|
67
73
|
test_files:
|
68
|
-
- spec/spec_helper.rb
|
69
|
-
- spec/test_cache.rb
|
70
74
|
- spec/cachy/memcached_wrapper_spec.rb
|
71
75
|
- spec/cachy/moneta_wrapper_spec.rb
|
72
76
|
- spec/cachy_spec.rb
|
77
|
+
- spec/test_cache.rb
|
78
|
+
- spec/spec_helper.rb
|
data/rdoc/README.rdoc
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
documentation is at http://github.com/grosser/cachy
|