timedcache 0.3 → 0.4.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/Rakefile +28 -13
- data/lib/timedcache.rb +68 -54
- data/lib/timedcache/version.rb +3 -0
- data/misc/thread_test.rb +3 -3
- data/test/test_timed_cache.rb +115 -0
- data/timedcache.gemspec +15 -0
- metadata +40 -32
- data/spec/timed_cache_spec.rb +0 -102
data/Rakefile
CHANGED
@@ -1,16 +1,31 @@
|
|
1
|
-
|
1
|
+
$LOAD_PATH.unshift(File.expand_path('../lib', __FILE__))
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
|
-
require '
|
5
|
-
require '
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
4
|
+
require 'rake/gempackagetask'
|
5
|
+
require 'rake/testtask'
|
6
|
+
|
7
|
+
# ============================================================================
|
8
|
+
|
9
|
+
# If you're using this file as a template to set up a new gem, this constant
|
10
|
+
# is the only thing you should need to change in the Rakefile:
|
11
|
+
GEM_NAME = 'timedcache'
|
12
|
+
|
13
|
+
# ============================================================================
|
14
|
+
|
15
|
+
Rake::TestTask.new do |t|
|
16
|
+
t.libs << 'test'
|
17
|
+
end
|
18
|
+
|
19
|
+
# ============================================================================
|
20
|
+
# = Gem package and release stuff.
|
21
|
+
# ============================================================================
|
22
|
+
|
23
|
+
spec = eval(File.read(File.join(File.dirname(__FILE__), "#{GEM_NAME}.gemspec")))
|
24
|
+
|
25
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
26
|
+
pkg.need_tar = true
|
16
27
|
end
|
28
|
+
|
29
|
+
# ============================================================================
|
30
|
+
|
31
|
+
task :default => [:test]
|
data/lib/timedcache.rb
CHANGED
@@ -2,59 +2,58 @@ require "pstore"
|
|
2
2
|
require "monitor"
|
3
3
|
|
4
4
|
# == TimedCache
|
5
|
-
#
|
5
|
+
#
|
6
6
|
# TimedCache implements a cache in which you can place objects
|
7
7
|
# and specify a timeout value.
|
8
|
-
#
|
8
|
+
#
|
9
9
|
# If you attempt to retrieve the object within the specified timeout
|
10
10
|
# period, the object will be returned. If the timeout period has elapsed,
|
11
11
|
# the TimedCache will return nil.
|
12
|
-
#
|
12
|
+
#
|
13
13
|
# e.g.:
|
14
14
|
# cache = TimedCache.new
|
15
15
|
# cache.put :my_object_key, "Expensive data", 10 # => "Expensive data"
|
16
|
-
#
|
16
|
+
#
|
17
17
|
# cache.get :my_object_key # => "Expensive data"
|
18
18
|
# cache[:my_object_key] # => "Expensive data"
|
19
|
-
#
|
19
|
+
#
|
20
20
|
# ... 10 seconds later:
|
21
21
|
# cache.get :my_object_key # => nil
|
22
|
-
#
|
22
|
+
#
|
23
23
|
# === Default timeout
|
24
|
-
#
|
24
|
+
#
|
25
25
|
# When creating a new TimedCache, a default timeout value can be set. This value
|
26
26
|
# will be used for each object added to the cache, unless a different timeout value
|
27
27
|
# is specifically set for that object.
|
28
|
-
#
|
28
|
+
#
|
29
29
|
# e.g.:
|
30
|
-
#
|
30
|
+
#
|
31
31
|
# cache = TimedCache.new(:default_timeout => 120)
|
32
32
|
# cache.default_timeout # => 120
|
33
|
-
#
|
33
|
+
#
|
34
34
|
# === File-based cache
|
35
|
-
#
|
36
|
-
# By default, TimedCache will use an in-memory store. A file-based store (using the
|
35
|
+
#
|
36
|
+
# By default, TimedCache will use an in-memory store. A file-based store (using the
|
37
37
|
# PStore library) can also be used.
|
38
|
-
#
|
38
|
+
#
|
39
39
|
# e.g.:
|
40
|
-
#
|
40
|
+
#
|
41
41
|
# TimedCache.new(:type => :file, :filename => "my_cache.db")
|
42
|
-
#
|
43
|
-
# The file-based cache makes it possible to easily share a cache between several ruby
|
44
|
-
# processes.
|
45
|
-
#
|
46
|
-
#
|
42
|
+
#
|
43
|
+
# The file-based cache makes it possible to easily share a cache between several ruby
|
44
|
+
# processes.
|
45
|
+
#
|
47
46
|
# Note that objects that cannot be marshalled (e.g. a Proc) can't be stored using the file-based cache.
|
48
47
|
class TimedCache
|
49
48
|
VERSION = "0.3"
|
50
|
-
|
49
|
+
|
51
50
|
attr_reader :default_timeout
|
52
|
-
|
51
|
+
|
53
52
|
# Create a new TimedCache. Available options are:
|
54
53
|
# <tt>type</tt>:: <tt>:memory</tt> or <tt>:file</tt> (defaults to <tt>:memory</tt>).
|
55
54
|
# <tt>default_timeout</tt>:: Timeout to use if none is specified when adding an object to the cache.
|
56
55
|
# <tt>filename</tt>:: Must be specified when using the <tt>:file</tt> type store.
|
57
|
-
#
|
56
|
+
#
|
58
57
|
# e.g.:
|
59
58
|
# TimedCache.new(:type => :file, :filename => "cache.db")
|
60
59
|
def initialize(opts = {})
|
@@ -63,66 +62,73 @@ class TimedCache
|
|
63
62
|
@store = new_store(opts)
|
64
63
|
@store.extend(MonitorMixin)
|
65
64
|
end
|
66
|
-
|
65
|
+
|
67
66
|
# Add an object to the cache. e.g.:
|
68
67
|
# cache.put(:session_id, 12345)
|
69
|
-
#
|
70
|
-
# The third parameter is an optional timeout value. If not specified, the
|
68
|
+
#
|
69
|
+
# The third parameter is an optional timeout value. If not specified, the
|
71
70
|
# <tt>:default_timeout</tt> for this TimedCache will be used instead.
|
72
71
|
def put(key, value, timeout = @default_timeout)
|
73
72
|
@store.synchronize do
|
74
73
|
@store.put(key, value, timeout) unless value.nil?
|
75
74
|
end
|
76
75
|
end
|
77
|
-
|
76
|
+
alias :set :put
|
77
|
+
|
78
|
+
# Remove an object from the cache. e.g.:
|
79
|
+
# cache.del(:session_id)
|
80
|
+
def delete(key)
|
81
|
+
@store.delete(key)
|
82
|
+
end
|
83
|
+
alias :del :delete
|
84
|
+
|
78
85
|
# Retrieve the object which the given +key+. If the object has expired or
|
79
86
|
# is not present, +nil+ is returned.
|
80
|
-
#
|
87
|
+
#
|
81
88
|
# Optionally, a block can be given. The result of evaluating the block will
|
82
89
|
# be substituted as the cache value, if the cache has expired.
|
83
|
-
#
|
90
|
+
#
|
84
91
|
# e.g.:
|
85
|
-
#
|
92
|
+
#
|
86
93
|
# cache.get("slow_database_query") do
|
87
94
|
# MyDatabase.query("SELECT * FROM bigtable...")
|
88
95
|
# end
|
89
|
-
#
|
90
|
-
# The block syntax can also be used with the in-memory cache.
|
96
|
+
#
|
91
97
|
def get(key, &block)
|
92
98
|
@store.synchronize do
|
93
99
|
@store.get(key, &block)
|
94
100
|
end
|
95
101
|
end
|
96
|
-
|
102
|
+
|
97
103
|
# Add to the cache using a hash-like syntax. e.g.:
|
98
104
|
# cache[:name] = "Nick"
|
99
|
-
#
|
105
|
+
#
|
100
106
|
# Note that adding to the cache this way does not allow you to specify timeout values
|
101
107
|
# on a per-object basis.
|
102
108
|
def []=(key, value)
|
103
109
|
put(key, value)
|
104
110
|
end
|
105
|
-
|
111
|
+
|
106
112
|
# Fetch objects using the hash syntax. e.g.:
|
107
113
|
# cache[:name] # => "Nick"
|
108
114
|
def [](key)
|
109
115
|
get(key)
|
110
116
|
end
|
111
|
-
|
117
|
+
|
112
118
|
protected
|
113
|
-
|
119
|
+
|
114
120
|
def new_store(options) #:nodoc:
|
115
121
|
self.class.const_get(options[:type].to_s.capitalize + "Store").new(self, options)
|
116
122
|
end
|
117
|
-
|
123
|
+
|
118
124
|
class Store #:nodoc:
|
119
125
|
def initialize(timed_cache, options)
|
120
126
|
@timed_cache = timed_cache
|
121
127
|
@options = options
|
122
128
|
end
|
123
|
-
|
129
|
+
|
124
130
|
protected
|
125
|
-
|
131
|
+
|
126
132
|
def generic_get(key, timeout, callback, fetch_key = lambda {|k| @cache[key]})
|
127
133
|
if object_store = fetch_key.call(key)
|
128
134
|
if object_store.expired?
|
@@ -139,40 +145,44 @@ class TimedCache
|
|
139
145
|
run_callback_and_add_to_cache(key, object_store, callback, timeout)
|
140
146
|
end
|
141
147
|
end
|
142
|
-
|
148
|
+
|
143
149
|
def run_callback_and_add_to_cache(key, object_store, callback, timeout)
|
144
150
|
object_store.no_expiry! if object_store
|
145
|
-
|
151
|
+
|
146
152
|
begin
|
147
153
|
result = callback.call
|
148
154
|
rescue
|
149
155
|
object_store.reset_expiry! if object_store
|
150
156
|
raise
|
151
157
|
end
|
152
|
-
|
158
|
+
|
153
159
|
@timed_cache.put(key, result, timeout)
|
154
160
|
result
|
155
161
|
end
|
156
162
|
end
|
157
|
-
|
163
|
+
|
158
164
|
class MemoryStore < Store #:nodoc:
|
159
165
|
def initialize(*args)
|
160
166
|
super(*args)
|
161
167
|
@cache = Hash.new
|
162
168
|
end
|
163
|
-
|
169
|
+
|
164
170
|
def put(key, value, timeout)
|
165
171
|
@cache[key] = ObjectContainer.new(value, timeout)
|
166
172
|
# Return just the given value, so that references to the
|
167
173
|
# ObjectStore instance can't be held outside this TimedCache:
|
168
174
|
value
|
169
175
|
end
|
170
|
-
|
176
|
+
|
171
177
|
def get(key, timeout = @timed_cache.default_timeout, &block)
|
172
178
|
generic_get(key, timeout, block)
|
173
179
|
end
|
180
|
+
|
181
|
+
def delete(key)
|
182
|
+
@cache.delete(key)
|
183
|
+
end
|
174
184
|
end
|
175
|
-
|
185
|
+
|
176
186
|
class FileStore < Store #:nodoc:
|
177
187
|
def initialize(*args)
|
178
188
|
super(*args)
|
@@ -182,15 +192,15 @@ class TimedCache
|
|
182
192
|
end
|
183
193
|
@cache = PStore.new(filename)
|
184
194
|
end
|
185
|
-
|
195
|
+
|
186
196
|
def put(key, value, timeout)
|
187
197
|
@cache.transaction { @cache[key] = ObjectContainer.new(value, timeout) }
|
188
|
-
|
198
|
+
|
189
199
|
# Return just the given value, so that references to the
|
190
200
|
# ObjectStore instance can't be held outside this TimedCache:
|
191
201
|
value
|
192
202
|
end
|
193
|
-
|
203
|
+
|
194
204
|
def get(key, timeout = @timed_cache.default_timeout, &block)
|
195
205
|
if block
|
196
206
|
generic_get(key, timeout, block, lambda {|k| @cache.transaction { @cache[key] } })
|
@@ -198,18 +208,22 @@ class TimedCache
|
|
198
208
|
@cache.transaction { generic_get(key, timeout, block) }
|
199
209
|
end
|
200
210
|
end
|
211
|
+
|
212
|
+
def delete(key)
|
213
|
+
@cache.transaction { @cache.delete(key) }
|
214
|
+
end
|
201
215
|
end
|
202
|
-
|
216
|
+
|
203
217
|
class ObjectContainer #:nodoc:
|
204
218
|
attr_accessor :object
|
205
|
-
|
219
|
+
|
206
220
|
def initialize(object, timeout)
|
207
221
|
@created_at = Time.now.utc
|
208
222
|
@timeout = timeout
|
209
223
|
@object = object
|
210
224
|
@frozen = false
|
211
225
|
end
|
212
|
-
|
226
|
+
|
213
227
|
def expired?
|
214
228
|
if @frozen
|
215
229
|
false
|
@@ -217,11 +231,11 @@ class TimedCache
|
|
217
231
|
(Time.now.utc - @timeout) > @created_at
|
218
232
|
end
|
219
233
|
end
|
220
|
-
|
234
|
+
|
221
235
|
def no_expiry!
|
222
236
|
@frozen = true
|
223
237
|
end
|
224
|
-
|
238
|
+
|
225
239
|
def reset_expiry!
|
226
240
|
@frozen = false
|
227
241
|
end
|
data/misc/thread_test.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
require File.
|
1
|
+
require File.expand_path('../lib/timedcache', File.dirname(__FILE__))
|
2
2
|
|
3
|
-
# This script will almost certainly raise an exception if
|
4
|
-
# thread
|
3
|
+
# This script will almost certainly raise an exception if the cache is not
|
4
|
+
# thread safe.
|
5
5
|
|
6
6
|
db = File.join(File.dirname(__FILE__), "thread_test.db")
|
7
7
|
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'timedcache'
|
3
|
+
|
4
|
+
class TimedCacheTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
@filename = File.join(File.dirname(__FILE__), "specs.db")
|
7
|
+
@memory_cache = TimedCache.new
|
8
|
+
@file_cache = TimedCache.new(:type => :file, :filename => @filename)
|
9
|
+
@caches = [@memory_cache, @file_cache]
|
10
|
+
end
|
11
|
+
|
12
|
+
def teardown
|
13
|
+
File.delete(@filename) if File.exist?(@filename)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_can_add_an_object_to_the_cache_specifying_a_timeout_value
|
17
|
+
@caches.each do |cache|
|
18
|
+
assert_equal("This needs caching", cache.put(:myobject, "This needs caching", 10))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_can_add_an_object_to_the_cache_specifying_a_timeout_value_using_the_set_method
|
23
|
+
@caches.each do |cache|
|
24
|
+
assert_equal("This needs caching", cache.set(:myobject, "This needs caching", 10))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_can_remove_objects_from_the_cache
|
29
|
+
@caches.each do |cache|
|
30
|
+
cache.put(:myobject, "This needs caching", 10)
|
31
|
+
assert_equal("This needs caching", cache.get(:myobject))
|
32
|
+
cache.del(:myobject)
|
33
|
+
assert_nil(cache.get(:myobject))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_cache_should_hold_seperate_values_for_each_key
|
38
|
+
@caches.each do |cache|
|
39
|
+
assert_equal("This needs caching", cache.put(:myobject, "This needs caching", 10))
|
40
|
+
assert_equal("...and this too", cache.put(:my_other_object, "...and this too", 10))
|
41
|
+
assert_equal("This needs caching", cache.get(:myobject))
|
42
|
+
assert_equal("...and this too", cache.get(:my_other_object))
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_string_and_symbol_keys_are_not_treated_as_equivalent
|
47
|
+
@caches.each do |cache|
|
48
|
+
cache[:symbolkey] = "Referenced by symbol"
|
49
|
+
cache["stringkey"] = "Referenced by string"
|
50
|
+
|
51
|
+
assert_equal("Referenced by symbol", cache[:symbolkey])
|
52
|
+
assert_nil(cache["symbolkey"])
|
53
|
+
|
54
|
+
assert_equal("Referenced by string", cache["stringkey"])
|
55
|
+
assert_nil(cache[:stringkey])
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_after_the_specified_timeout_value_has_elapsed_nil_should_be_returned
|
60
|
+
@caches.each do |cache|
|
61
|
+
assert_equal("This needs caching", cache.put(:myobject, "This needs caching", 0))
|
62
|
+
assert_nil(cache.get(:myobject))
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_if_no_object_matching_the_given_key_is_found_nil_should_be_returned
|
67
|
+
@caches.each do |cache|
|
68
|
+
assert_nil(cache.get(:my_nonexistant_object))
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_should_be_able_to_use_an_array_as_a_cache_key
|
73
|
+
@caches.each do |cache|
|
74
|
+
assert_equal("Array", cache.put([123,234], "Array"))
|
75
|
+
assert_equal("Array", cache.get([123,234]))
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_passing_a_block_to_the_get_method_should_substitute_result_of_block_as_value_for_given_key
|
80
|
+
@caches.each do |cache|
|
81
|
+
cache.put("block_test", 1984, 0)
|
82
|
+
assert_equal(2001, cache.get("block_test") { 2001 })
|
83
|
+
assert_equal(2001, cache.get("block_test"))
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_passing_block_to_get_should_add_result_of_callback_when_there_is_no_existing_value
|
88
|
+
@caches.each do |cache|
|
89
|
+
assert_equal(nil, cache.get("new_key_with_block"))
|
90
|
+
assert_equal("Nicholas", cache.get("new_key_with_block") { "Nicholas" })
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_is_able_to_specify_default_timeout_when_creating_an_instance
|
95
|
+
cache = TimedCache.new(:default_timeout => 20)
|
96
|
+
assert_equal(20, cache.default_timeout)
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_if_no_default_timeout_is_set_60_seconds_should_be_used
|
100
|
+
cache = TimedCache.new
|
101
|
+
assert_equal(60, cache.default_timeout)
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_timeout_specified_when_putting_a_new_object_into_the_cache_should_override_default_timeout
|
105
|
+
cache = TimedCache.new(:default_timeout => 20)
|
106
|
+
assert_equal(20, cache.default_timeout)
|
107
|
+
cache.put("alternative_timeout", "2 minutes", 120)
|
108
|
+
|
109
|
+
timeout = cache.instance_variable_get(:@store).
|
110
|
+
instance_variable_get(:@cache)["alternative_timeout"].
|
111
|
+
instance_variable_get(:@timeout)
|
112
|
+
|
113
|
+
assert_equal(120, timeout)
|
114
|
+
end
|
115
|
+
end
|
data/timedcache.gemspec
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'timedcache/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = "timedcache"
|
5
|
+
s.version = TimedCache::VERSION
|
6
|
+
s.summary = %q{TimedCache implements a cache in which you can place objects and specify a timeout value.}
|
7
|
+
s.description = %q{TimedCache implements a cache in which you can place objects and specify a timeout value. If you attempt to retrieve the object within the specified timeout, the object will be returned. If the timeout period has elapsed, the TimedCache will return nil.}
|
8
|
+
s.files = Dir['**/*']
|
9
|
+
s.authors = ["Nicholas Dainty"]
|
10
|
+
s.email = "nick@npad.co.uk"
|
11
|
+
s.homepage = "http://timedcache.rubyforge.org/"
|
12
|
+
s.has_rdoc = true
|
13
|
+
s.rdoc_options = ["--charset=UTF-8", "--line-numbers", "--inline-source"]
|
14
|
+
s.required_ruby_version = '>= 1.8.6'
|
15
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: timedcache
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 15
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 4
|
9
|
+
- 0
|
10
|
+
version: 0.4.0
|
5
11
|
platform: ruby
|
6
12
|
authors:
|
7
13
|
- Nicholas Dainty
|
@@ -9,64 +15,66 @@ autorequire:
|
|
9
15
|
bindir: bin
|
10
16
|
cert_chain: []
|
11
17
|
|
12
|
-
date:
|
18
|
+
date: 2011-03-24 00:00:00 +00:00
|
13
19
|
default_executable:
|
14
|
-
dependencies:
|
15
|
-
|
16
|
-
|
17
|
-
type: :development
|
18
|
-
version_requirement:
|
19
|
-
version_requirements: !ruby/object:Gem::Requirement
|
20
|
-
requirements:
|
21
|
-
- - ">="
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version: 1.8.2
|
24
|
-
version:
|
25
|
-
description: TimedCache implements a cache in which you can place objects and specify a timeout value. If you attempt to retrieve the object within the specified timeout period, the object will be returned. If the timeout period has elapsed, the TimedCache will return nil.
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: TimedCache implements a cache in which you can place objects and specify a timeout value. If you attempt to retrieve the object within the specified timeout, the object will be returned. If the timeout period has elapsed, the TimedCache will return nil.
|
26
23
|
email: nick@npad.co.uk
|
27
24
|
executables: []
|
28
25
|
|
29
26
|
extensions: []
|
30
27
|
|
31
|
-
extra_rdoc_files:
|
32
|
-
|
33
|
-
- Manifest.txt
|
34
|
-
- README.txt
|
28
|
+
extra_rdoc_files: []
|
29
|
+
|
35
30
|
files:
|
36
31
|
- History.txt
|
37
|
-
- Manifest.txt
|
38
|
-
- README.txt
|
39
|
-
- Rakefile
|
40
32
|
- lib/timed_cache.rb
|
33
|
+
- lib/timedcache/version.rb
|
41
34
|
- lib/timedcache.rb
|
35
|
+
- Manifest.txt
|
42
36
|
- misc/thread_test.rb
|
43
|
-
-
|
37
|
+
- Rakefile
|
38
|
+
- README.txt
|
39
|
+
- test/test_timed_cache.rb
|
40
|
+
- timedcache.gemspec
|
44
41
|
has_rdoc: true
|
45
|
-
homepage:
|
42
|
+
homepage: http://timedcache.rubyforge.org/
|
43
|
+
licenses: []
|
44
|
+
|
46
45
|
post_install_message:
|
47
46
|
rdoc_options:
|
48
|
-
- --
|
49
|
-
-
|
47
|
+
- --charset=UTF-8
|
48
|
+
- --line-numbers
|
49
|
+
- --inline-source
|
50
50
|
require_paths:
|
51
51
|
- lib
|
52
52
|
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
53
54
|
requirements:
|
54
55
|
- - ">="
|
55
56
|
- !ruby/object:Gem::Version
|
56
|
-
|
57
|
-
|
57
|
+
hash: 59
|
58
|
+
segments:
|
59
|
+
- 1
|
60
|
+
- 8
|
61
|
+
- 6
|
62
|
+
version: 1.8.6
|
58
63
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
59
65
|
requirements:
|
60
66
|
- - ">="
|
61
67
|
- !ruby/object:Gem::Version
|
68
|
+
hash: 3
|
69
|
+
segments:
|
70
|
+
- 0
|
62
71
|
version: "0"
|
63
|
-
version:
|
64
72
|
requirements: []
|
65
73
|
|
66
|
-
rubyforge_project:
|
67
|
-
rubygems_version: 1.3
|
74
|
+
rubyforge_project:
|
75
|
+
rubygems_version: 1.5.3
|
68
76
|
signing_key:
|
69
|
-
specification_version:
|
70
|
-
summary:
|
77
|
+
specification_version: 3
|
78
|
+
summary: TimedCache implements a cache in which you can place objects and specify a timeout value.
|
71
79
|
test_files: []
|
72
80
|
|
data/spec/timed_cache_spec.rb
DELETED
@@ -1,102 +0,0 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), "../lib/timedcache")
|
2
|
-
|
3
|
-
$filename = File.join(File.dirname(__FILE__), "specs.db")
|
4
|
-
|
5
|
-
describe "Adding and retrieving objects from the cache" do
|
6
|
-
before(:each) do
|
7
|
-
@memory_cache = TimedCache.new
|
8
|
-
@file_cache = TimedCache.new(:type => :file, :filename => $filename)
|
9
|
-
@caches = [@memory_cache, @file_cache]
|
10
|
-
end
|
11
|
-
|
12
|
-
after do
|
13
|
-
File.delete($filename)
|
14
|
-
end
|
15
|
-
|
16
|
-
it "Can add an object to the cache, specifying a timeout value" do
|
17
|
-
@caches.each do |cache|
|
18
|
-
cache.put(:myobject, "This needs caching", 10).should == "This needs caching"
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
it "Cache should hold seperate values for each key" do
|
23
|
-
@caches.each do |cache|
|
24
|
-
cache.put(:myobject, "This needs caching", 10).should == "This needs caching"
|
25
|
-
cache.put(:my_other_object, "...and this too", 10).should == "...and this too"
|
26
|
-
cache.get(:myobject).should == "This needs caching"
|
27
|
-
cache.get(:my_other_object).should == "...and this too"
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
it "String and symbol keys are not treated as equivalent" do
|
32
|
-
@caches.each do |cache|
|
33
|
-
cache[:symbolkey] = "Referenced by symbol"
|
34
|
-
cache["stringkey"] = "Referenced by string"
|
35
|
-
|
36
|
-
cache[:symbolkey].should == "Referenced by symbol"
|
37
|
-
cache["symbolkey"].should == nil
|
38
|
-
|
39
|
-
cache["stringkey"].should == "Referenced by string"
|
40
|
-
cache[:stringkey].should == nil
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
it "After the specified timeout value has elapsed, nil should be returned" do
|
45
|
-
@caches.each do |cache|
|
46
|
-
cache.put(:myobject, "This needs caching", 0).should == "This needs caching"
|
47
|
-
cache.get(:myobject).should == nil
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
it "If no object matching the given key is found, nil should be returned" do
|
52
|
-
@caches.each do |cache|
|
53
|
-
cache.get(:my_nonexistant_object).should == nil
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
it "Should be able to use an array as a cache key" do
|
58
|
-
@caches.each do |cache|
|
59
|
-
cache.put([123,234], "Array").should == "Array"
|
60
|
-
cache.get([123,234]).should == "Array"
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
it "Passing a block to the TimedCache#get method should substitute the " +
|
65
|
-
"result of the block as the value for the given key" do
|
66
|
-
@caches.each do |cache|
|
67
|
-
cache.put("block_test", 1984, 0)
|
68
|
-
cache.get("block_test") { 2001 }.should == 2001
|
69
|
-
cache.get("block_test").should == 2001
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
it "Passing a block to TimedCache#get should add the result of the callback " +
|
74
|
-
"when there is no existing value for the key given" do
|
75
|
-
@caches.each do |cache|
|
76
|
-
cache.get("new_key_with_block").should == nil
|
77
|
-
cache.get("new_key_with_block") { "Nicholas" }.should == "Nicholas"
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
describe "Specifying a default timeout" do
|
83
|
-
it "Should be able to it a default timeout when creating a TimedCache" do
|
84
|
-
cache = TimedCache.new(:default_timeout => 20)
|
85
|
-
cache.should be_kind_of(TimedCache)
|
86
|
-
cache.default_timeout.should == 20
|
87
|
-
end
|
88
|
-
|
89
|
-
it "If no default timeout is set, 60 seconds should be used" do
|
90
|
-
cache = TimedCache.new
|
91
|
-
cache.should be_kind_of(TimedCache)
|
92
|
-
cache.default_timeout.should == 60
|
93
|
-
end
|
94
|
-
|
95
|
-
it "Timeout specified when putting a new object into the cache should override default timeout" do
|
96
|
-
cache = TimedCache.new(:default_timeout => 20)
|
97
|
-
cache.default_timeout.should == 20
|
98
|
-
cache.put("alternative_timeout", "2 minutes", 120)
|
99
|
-
cache.instance_variable_get(:@store).instance_variable_get(:@cache)["alternative_timeout"].
|
100
|
-
instance_variable_get(:@timeout).should == 120
|
101
|
-
end
|
102
|
-
end
|