timedcache 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT_LICENSE +7 -0
- data/doc/created.rid +1 -0
- data/doc/fr_class_index.html +27 -0
- data/doc/fr_file_index.html +29 -0
- data/doc/fr_method_index.html +31 -0
- data/doc/index.html +24 -0
- data/doc/rdoc-style.css +208 -0
- data/lib/timed_cache.rb +2 -0
- data/lib/timedcache.rb +175 -0
- data/specs/timed_cache_spec.rb +67 -0
- metadata +60 -0
data/MIT_LICENSE
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
Copyright (c) 2006 Nicholas Dainty
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
4
|
+
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/doc/created.rid
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Thu Dec 07 18:24:58 GMT 2006
|
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
3
|
+
<!DOCTYPE html
|
4
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
5
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
6
|
+
|
7
|
+
<!--
|
8
|
+
|
9
|
+
Classes
|
10
|
+
|
11
|
+
-->
|
12
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
13
|
+
<head>
|
14
|
+
<title>Classes</title>
|
15
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
16
|
+
<link rel="stylesheet" href="rdoc-style.css" type="text/css" />
|
17
|
+
<base target="docwin" />
|
18
|
+
</head>
|
19
|
+
<body>
|
20
|
+
<div id="index">
|
21
|
+
<h1 class="section-bar">Classes</h1>
|
22
|
+
<div id="index-entries">
|
23
|
+
<a href="classes/TimedCache.html">TimedCache</a><br />
|
24
|
+
</div>
|
25
|
+
</div>
|
26
|
+
</body>
|
27
|
+
</html>
|
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
3
|
+
<!DOCTYPE html
|
4
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
5
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
6
|
+
|
7
|
+
<!--
|
8
|
+
|
9
|
+
Files
|
10
|
+
|
11
|
+
-->
|
12
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
13
|
+
<head>
|
14
|
+
<title>Files</title>
|
15
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
16
|
+
<link rel="stylesheet" href="rdoc-style.css" type="text/css" />
|
17
|
+
<base target="docwin" />
|
18
|
+
</head>
|
19
|
+
<body>
|
20
|
+
<div id="index">
|
21
|
+
<h1 class="section-bar">Files</h1>
|
22
|
+
<div id="index-entries">
|
23
|
+
<a href="files/MIT_LICENSE.html">MIT_LICENSE</a><br />
|
24
|
+
<a href="files/lib/timed_cache_rb.html">lib/timed_cache.rb</a><br />
|
25
|
+
<a href="files/lib/timedcache_rb.html">lib/timedcache.rb</a><br />
|
26
|
+
</div>
|
27
|
+
</div>
|
28
|
+
</body>
|
29
|
+
</html>
|
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
3
|
+
<!DOCTYPE html
|
4
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
5
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
6
|
+
|
7
|
+
<!--
|
8
|
+
|
9
|
+
Methods
|
10
|
+
|
11
|
+
-->
|
12
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
13
|
+
<head>
|
14
|
+
<title>Methods</title>
|
15
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
16
|
+
<link rel="stylesheet" href="rdoc-style.css" type="text/css" />
|
17
|
+
<base target="docwin" />
|
18
|
+
</head>
|
19
|
+
<body>
|
20
|
+
<div id="index">
|
21
|
+
<h1 class="section-bar">Methods</h1>
|
22
|
+
<div id="index-entries">
|
23
|
+
<a href="classes/TimedCache.html#M000005">[] (TimedCache)</a><br />
|
24
|
+
<a href="classes/TimedCache.html#M000004">[]= (TimedCache)</a><br />
|
25
|
+
<a href="classes/TimedCache.html#M000003">get (TimedCache)</a><br />
|
26
|
+
<a href="classes/TimedCache.html#M000001">new (TimedCache)</a><br />
|
27
|
+
<a href="classes/TimedCache.html#M000002">put (TimedCache)</a><br />
|
28
|
+
</div>
|
29
|
+
</div>
|
30
|
+
</body>
|
31
|
+
</html>
|
data/doc/index.html
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
2
|
+
<!DOCTYPE html
|
3
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
|
4
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
|
5
|
+
|
6
|
+
<!--
|
7
|
+
|
8
|
+
TimedCache Documentation
|
9
|
+
|
10
|
+
-->
|
11
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
12
|
+
<head>
|
13
|
+
<title>TimedCache Documentation</title>
|
14
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
15
|
+
</head>
|
16
|
+
<frameset rows="20%, 80%">
|
17
|
+
<frameset cols="25%,35%,45%">
|
18
|
+
<frame src="fr_file_index.html" title="Files" name="Files" />
|
19
|
+
<frame src="fr_class_index.html" name="Classes" />
|
20
|
+
<frame src="fr_method_index.html" name="Methods" />
|
21
|
+
</frameset>
|
22
|
+
<frame src="classes/TimedCache.html" name="docwin" />
|
23
|
+
</frameset>
|
24
|
+
</html>
|
data/doc/rdoc-style.css
ADDED
@@ -0,0 +1,208 @@
|
|
1
|
+
|
2
|
+
body {
|
3
|
+
font-family: Verdana,Arial,Helvetica,sans-serif;
|
4
|
+
font-size: 90%;
|
5
|
+
margin: 0;
|
6
|
+
margin-left: 40px;
|
7
|
+
padding: 0;
|
8
|
+
background: white;
|
9
|
+
}
|
10
|
+
|
11
|
+
h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; }
|
12
|
+
h1 { font-size: 150%; }
|
13
|
+
h2,h3,h4 { margin-top: 1em; }
|
14
|
+
|
15
|
+
a { background: #eef; color: #039; text-decoration: none; }
|
16
|
+
a:hover { background: #039; color: #eef; }
|
17
|
+
|
18
|
+
/* Override the base stylesheet's Anchor inside a table cell */
|
19
|
+
td > a {
|
20
|
+
background: transparent;
|
21
|
+
color: #039;
|
22
|
+
text-decoration: none;
|
23
|
+
}
|
24
|
+
|
25
|
+
/* and inside a section title */
|
26
|
+
.section-title > a {
|
27
|
+
background: transparent;
|
28
|
+
color: #eee;
|
29
|
+
text-decoration: none;
|
30
|
+
}
|
31
|
+
|
32
|
+
/* === Structural elements =================================== */
|
33
|
+
|
34
|
+
div#index {
|
35
|
+
margin: 0;
|
36
|
+
margin-left: -40px;
|
37
|
+
padding: 0;
|
38
|
+
font-size: 90%;
|
39
|
+
}
|
40
|
+
|
41
|
+
|
42
|
+
div#index a {
|
43
|
+
margin-left: 0.7em;
|
44
|
+
}
|
45
|
+
|
46
|
+
div#index .section-bar {
|
47
|
+
margin-left: 0px;
|
48
|
+
padding-left: 0.7em;
|
49
|
+
background: #ccc;
|
50
|
+
font-size: small;
|
51
|
+
}
|
52
|
+
|
53
|
+
|
54
|
+
div#classHeader, div#fileHeader {
|
55
|
+
width: auto;
|
56
|
+
color: white;
|
57
|
+
padding: 0.5em 1.5em 0.5em 1.5em;
|
58
|
+
margin: 0;
|
59
|
+
margin-left: -40px;
|
60
|
+
border-bottom: 3px solid #006;
|
61
|
+
}
|
62
|
+
|
63
|
+
div#classHeader a, div#fileHeader a {
|
64
|
+
background: inherit;
|
65
|
+
color: white;
|
66
|
+
}
|
67
|
+
|
68
|
+
div#classHeader td, div#fileHeader td {
|
69
|
+
background: inherit;
|
70
|
+
color: white;
|
71
|
+
}
|
72
|
+
|
73
|
+
|
74
|
+
div#fileHeader {
|
75
|
+
background: #057;
|
76
|
+
}
|
77
|
+
|
78
|
+
div#classHeader {
|
79
|
+
background: #048;
|
80
|
+
}
|
81
|
+
|
82
|
+
|
83
|
+
.class-name-in-header {
|
84
|
+
font-size: 180%;
|
85
|
+
font-weight: bold;
|
86
|
+
}
|
87
|
+
|
88
|
+
|
89
|
+
div#bodyContent {
|
90
|
+
padding: 0 1.5em 0 1.5em;
|
91
|
+
}
|
92
|
+
|
93
|
+
div#description {
|
94
|
+
padding: 0.5em 1.5em;
|
95
|
+
background: #efefef;
|
96
|
+
border: 1px dotted #999;
|
97
|
+
}
|
98
|
+
|
99
|
+
div#description h1,h2,h3,h4,h5,h6 {
|
100
|
+
color: #125;;
|
101
|
+
background: transparent;
|
102
|
+
}
|
103
|
+
|
104
|
+
div#validator-badges {
|
105
|
+
text-align: center;
|
106
|
+
}
|
107
|
+
div#validator-badges img { border: 0; }
|
108
|
+
|
109
|
+
div#copyright {
|
110
|
+
color: #333;
|
111
|
+
background: #efefef;
|
112
|
+
font: 0.75em sans-serif;
|
113
|
+
margin-top: 5em;
|
114
|
+
margin-bottom: 0;
|
115
|
+
padding: 0.5em 2em;
|
116
|
+
}
|
117
|
+
|
118
|
+
|
119
|
+
/* === Classes =================================== */
|
120
|
+
|
121
|
+
table.header-table {
|
122
|
+
color: white;
|
123
|
+
font-size: small;
|
124
|
+
}
|
125
|
+
|
126
|
+
.type-note {
|
127
|
+
font-size: small;
|
128
|
+
color: #DEDEDE;
|
129
|
+
}
|
130
|
+
|
131
|
+
.xxsection-bar {
|
132
|
+
background: #eee;
|
133
|
+
color: #333;
|
134
|
+
padding: 3px;
|
135
|
+
}
|
136
|
+
|
137
|
+
.section-bar {
|
138
|
+
color: #333;
|
139
|
+
border-bottom: 1px solid #999;
|
140
|
+
margin-left: -20px;
|
141
|
+
}
|
142
|
+
|
143
|
+
|
144
|
+
.section-title {
|
145
|
+
background: #79a;
|
146
|
+
color: #eee;
|
147
|
+
padding: 3px;
|
148
|
+
margin-top: 2em;
|
149
|
+
margin-left: -30px;
|
150
|
+
border: 1px solid #999;
|
151
|
+
}
|
152
|
+
|
153
|
+
.top-aligned-row { vertical-align: top }
|
154
|
+
.bottom-aligned-row { vertical-align: bottom }
|
155
|
+
|
156
|
+
/* --- Context section classes ----------------------- */
|
157
|
+
|
158
|
+
.context-row { }
|
159
|
+
.context-item-name { font-family: monospace; font-weight: bold; color: black; }
|
160
|
+
.context-item-value { font-size: small; color: #448; }
|
161
|
+
.context-item-desc { color: #333; padding-left: 2em; }
|
162
|
+
|
163
|
+
/* --- Method classes -------------------------- */
|
164
|
+
.method-detail {
|
165
|
+
background: #efefef;
|
166
|
+
padding: 0;
|
167
|
+
margin-top: 0.5em;
|
168
|
+
margin-bottom: 1em;
|
169
|
+
border: 1px dotted #ccc;
|
170
|
+
}
|
171
|
+
.method-heading {
|
172
|
+
color: black;
|
173
|
+
background: #ccc;
|
174
|
+
border-bottom: 1px solid #666;
|
175
|
+
padding: 0.2em 0.5em 0 0.5em;
|
176
|
+
}
|
177
|
+
.method-signature { color: black; background: inherit; }
|
178
|
+
.method-name { font-weight: bold; }
|
179
|
+
.method-args { font-style: italic; }
|
180
|
+
.method-description { padding: 0 0.5em 0 0.5em; }
|
181
|
+
|
182
|
+
/* --- Source code sections -------------------- */
|
183
|
+
|
184
|
+
a.source-toggle { font-size: 90%; }
|
185
|
+
div.method-source-code {
|
186
|
+
background: #262626;
|
187
|
+
color: #ffdead;
|
188
|
+
margin: 1em;
|
189
|
+
padding: 0.5em;
|
190
|
+
border: 1px dashed #999;
|
191
|
+
overflow: hidden;
|
192
|
+
}
|
193
|
+
|
194
|
+
div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
195
|
+
|
196
|
+
/* --- Ruby keyword styles --------------------- */
|
197
|
+
|
198
|
+
.standalone-code { background: #221111; color: #ffdead; overflow: hidden; }
|
199
|
+
|
200
|
+
.ruby-constant { color: #7fffd4; background: transparent; }
|
201
|
+
.ruby-keyword { color: #00ffff; background: transparent; }
|
202
|
+
.ruby-ivar { color: #eedd82; background: transparent; }
|
203
|
+
.ruby-operator { color: #00ffee; background: transparent; }
|
204
|
+
.ruby-identifier { color: #ffdead; background: transparent; }
|
205
|
+
.ruby-node { color: #ffa07a; background: transparent; }
|
206
|
+
.ruby-comment { color: #b22222; font-weight: bold; background: transparent; }
|
207
|
+
.ruby-regexp { color: #ffa07a; background: transparent; }
|
208
|
+
.ruby-value { color: #7fffd4; background: transparent; }
|
data/lib/timed_cache.rb
ADDED
data/lib/timedcache.rb
ADDED
@@ -0,0 +1,175 @@
|
|
1
|
+
require "pstore"
|
2
|
+
|
3
|
+
# == TimedCache
|
4
|
+
#
|
5
|
+
# TimedCache implements a cache in which you can place objects
|
6
|
+
# and specify a timeout value.
|
7
|
+
#
|
8
|
+
# If you attempt to retrieve the object within the specified timeout
|
9
|
+
# period, the object will be returned. If the timeout period has elapsed,
|
10
|
+
# the TimedCache will return nil.
|
11
|
+
#
|
12
|
+
# e.g.:
|
13
|
+
# cache = TimedCache.new
|
14
|
+
# cache.put :my_object_key, "Expensive data", 10 # => "Expensive data"
|
15
|
+
#
|
16
|
+
# cache.get :my_object_key # => "Expensive data"
|
17
|
+
# cache[:my_object_key] # => "Expensive data"
|
18
|
+
#
|
19
|
+
# ... 10 seconds later:
|
20
|
+
# cache.get :my_object_key # => nil
|
21
|
+
#
|
22
|
+
# === Default timeout
|
23
|
+
#
|
24
|
+
# When creating a new TimedCache, a default timeout value can be set. This value
|
25
|
+
# will be used for each object added to the cache, unless a different timeout value
|
26
|
+
# is specifically set for that object.
|
27
|
+
#
|
28
|
+
# e.g.:
|
29
|
+
#
|
30
|
+
# cache = TimedCache.new(:default_timeout => 120)
|
31
|
+
# cache.default_timeout # => 120
|
32
|
+
#
|
33
|
+
# === File-based cache
|
34
|
+
#
|
35
|
+
# By default, TimedCache will use an in-memory store. A file-based store (using the
|
36
|
+
# PStore library) can also be used.
|
37
|
+
#
|
38
|
+
# e.g.:
|
39
|
+
#
|
40
|
+
# TimedCache.new(:type => :file, :filename => "my_cache.db")
|
41
|
+
#
|
42
|
+
# Note that objects that cannot be marshalled (e.g. a Proc) can't be stored using the file-based cache.
|
43
|
+
class TimedCache
|
44
|
+
Version = "0.1"
|
45
|
+
|
46
|
+
attr_reader :default_timeout
|
47
|
+
|
48
|
+
# Create a new TimedCache. Available options are:
|
49
|
+
# <tt>type</tt>:: <tt>:memory</tt> or <tt>:file</tt> (defaults to <tt>:memory</tt>).
|
50
|
+
# <tt>default_timeout</tt>:: Timeout to use if none is specified when adding an object to the cache.
|
51
|
+
# <tt>filename</tt>:: Must be specified when using the <tt>:file</tt> type store.
|
52
|
+
#
|
53
|
+
# e.g.:
|
54
|
+
# TimedCache.new(:type => :file, :filename => "cache.db")
|
55
|
+
def initialize(opts = {})
|
56
|
+
opts[:type] ||= :memory
|
57
|
+
@default_timeout = opts[:default_timeout] || 60
|
58
|
+
@store = new_store(opts)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Add an object to the cache. e.g.:
|
62
|
+
# cache.put(:session_id, 12345)
|
63
|
+
#
|
64
|
+
# The third parameter is an optional timeout value. If not specified, the
|
65
|
+
# <tt>:default_timeout</tt> for this TimedCache will be used instead.
|
66
|
+
def put(key, value, timeout = @default_timeout)
|
67
|
+
@store.put(key, value, timeout)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Retrieve the object which the given +key+. If the object has expired or
|
71
|
+
# is not present, +nil+ is returned.
|
72
|
+
def get(key)
|
73
|
+
@store.get(key)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Add to the cache using a hash-like syntax. e.g.:
|
77
|
+
# cache[:name] = "Nick"
|
78
|
+
#
|
79
|
+
# Note that adding to the cache this way does not allow you to specify timeout values
|
80
|
+
# on a per-object basis.
|
81
|
+
def []=(key, value)
|
82
|
+
put(key, value)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Fetch objects using the hash syntax. e.g.:
|
86
|
+
# cache[:name] # => "Nick"
|
87
|
+
def [](key)
|
88
|
+
get(key)
|
89
|
+
end
|
90
|
+
|
91
|
+
protected
|
92
|
+
|
93
|
+
def new_store(options) #:nodoc:
|
94
|
+
self.class.const_get(options[:type].to_s.capitalize + "Store").new(options)
|
95
|
+
end
|
96
|
+
|
97
|
+
class Store #:nodoc:
|
98
|
+
def initialize(options)
|
99
|
+
@options = options
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
class MemoryStore < Store #:nodoc:
|
104
|
+
def initialize(options)
|
105
|
+
super
|
106
|
+
@cache = Hash.new
|
107
|
+
end
|
108
|
+
|
109
|
+
def put(key, value, timeout)
|
110
|
+
@cache[key.to_s.intern] = ObjectContainer.new(value, timeout)
|
111
|
+
# Return just the given value, so that references to the
|
112
|
+
# ObjectStore instance can't be held outside this TimedCache:
|
113
|
+
value
|
114
|
+
end
|
115
|
+
|
116
|
+
def get(key)
|
117
|
+
if object_store = @cache[key.to_s.intern]
|
118
|
+
if object_store.expired?
|
119
|
+
# Free up memory:
|
120
|
+
@cache[key.to_s.intern] = nil
|
121
|
+
else
|
122
|
+
object_store.object
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
class FileStore < Store #:nodoc:
|
129
|
+
def initialize(*args)
|
130
|
+
super(*args)
|
131
|
+
filename = @options[:filename]
|
132
|
+
unless filename
|
133
|
+
raise ArgumentError, ":filename option must be specified for :file type store."
|
134
|
+
end
|
135
|
+
@cache = PStore.new(filename)
|
136
|
+
end
|
137
|
+
|
138
|
+
def put(key, value, timeout = nil)
|
139
|
+
@cache.transaction do
|
140
|
+
@cache[key.to_s.intern] = ObjectContainer.new(value, timeout)
|
141
|
+
end
|
142
|
+
|
143
|
+
# Return just the given value, so that references to the
|
144
|
+
# ObjectStore instance can't be held outside this TimedCache:
|
145
|
+
value
|
146
|
+
end
|
147
|
+
|
148
|
+
def get(key)
|
149
|
+
@cache.transaction do
|
150
|
+
if object_store = @cache[key.to_s.intern]
|
151
|
+
if object_store.expired?
|
152
|
+
# Free up memory:
|
153
|
+
@cache[key.to_s.intern] = nil
|
154
|
+
else
|
155
|
+
object_store.object
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
class ObjectContainer #:nodoc:
|
163
|
+
attr_reader :object
|
164
|
+
|
165
|
+
def initialize(object, timeout)
|
166
|
+
@created_at = Time.now.utc
|
167
|
+
@timeout = timeout
|
168
|
+
@object = object
|
169
|
+
end
|
170
|
+
|
171
|
+
def expired?
|
172
|
+
(Time.now.utc - @timeout) > @created_at
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "../lib/timedcache")
|
2
|
+
|
3
|
+
$filename = File.join(File.dirname(__FILE__), "specs.db")
|
4
|
+
|
5
|
+
context "Adding and retrieving objects from the cache" do
|
6
|
+
setup 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
|
+
teardown do
|
13
|
+
File.delete($filename)
|
14
|
+
end
|
15
|
+
|
16
|
+
specify "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_equal "This needs caching"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
specify "Cache should hold seperate values for each key" do
|
23
|
+
@caches.each do |cache|
|
24
|
+
cache.put(:myobject, "This needs caching", 10).should_equal "This needs caching"
|
25
|
+
cache.put(:my_other_object, "...and this too", 10).should_equal "...and this too"
|
26
|
+
cache.get(:myobject).should_equal "This needs caching"
|
27
|
+
cache.get(:my_other_object).should_equal "...and this too"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
specify "After the specified timeout value has elapsed, nil should be returned" do
|
32
|
+
@caches.each do |cache|
|
33
|
+
cache.put(:myobject, "This needs caching", 0).should_equal "This needs caching"
|
34
|
+
cache.get(:myobject).should_equal nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
specify "If no object matching the given key is found, nil should be returned" do
|
39
|
+
@caches.each do |cache|
|
40
|
+
cache.get(:my_nonexistant_object).should_equal nil
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
specify "Should be able to use an array as a cache key" do
|
45
|
+
@caches.each do |cache|
|
46
|
+
cache.put([123,234], "Array").should_equal "Array"
|
47
|
+
cache.get([123,234]).should_equal "Array"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "Specifying a default timeout" do
|
53
|
+
specify "Should be able to specify a default timeout when creating a TimedCache" do
|
54
|
+
cache = TimedCache.new(:default_timeout => 20)
|
55
|
+
cache.should_be_kind_of TimedCache
|
56
|
+
cache.default_timeout.should_equal 20
|
57
|
+
end
|
58
|
+
|
59
|
+
specify "If no default timeout is set, 60 seconds should be used" do
|
60
|
+
cache = TimedCache.new
|
61
|
+
cache.should_be_kind_of TimedCache
|
62
|
+
cache.default_timeout.should_equal 60
|
63
|
+
end
|
64
|
+
|
65
|
+
specify "Timeout specified when putting a new object into the cache should override default timeout" do
|
66
|
+
end
|
67
|
+
end
|
metadata
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.0
|
3
|
+
specification_version: 1
|
4
|
+
name: timedcache
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: "0.1"
|
7
|
+
date: 2006-12-07 00:00:00 +00:00
|
8
|
+
summary: A very simple time-based object cache.
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: nick@npad.co.uk
|
12
|
+
homepage: http://timedcache.rubyforge.org
|
13
|
+
rubyforge_project: timedcache
|
14
|
+
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.
|
15
|
+
autorequire: timedcache
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Nicholas Dainty
|
31
|
+
files:
|
32
|
+
- doc/classes
|
33
|
+
- doc/created.rid
|
34
|
+
- doc/files
|
35
|
+
- doc/fr_class_index.html
|
36
|
+
- doc/fr_file_index.html
|
37
|
+
- doc/fr_method_index.html
|
38
|
+
- doc/index.html
|
39
|
+
- doc/rdoc-style.css
|
40
|
+
- lib/timed_cache.rb
|
41
|
+
- lib/timedcache.rb
|
42
|
+
- specs/timed_cache_spec.rb
|
43
|
+
- MIT_LICENSE
|
44
|
+
test_files: []
|
45
|
+
|
46
|
+
rdoc_options:
|
47
|
+
- --main
|
48
|
+
- TimedCache
|
49
|
+
- --line-numbers
|
50
|
+
- --inline-source
|
51
|
+
extra_rdoc_files:
|
52
|
+
- MIT_LICENSE
|
53
|
+
executables: []
|
54
|
+
|
55
|
+
extensions: []
|
56
|
+
|
57
|
+
requirements: []
|
58
|
+
|
59
|
+
dependencies: []
|
60
|
+
|