ruby-cache 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.
- data/Manual.rd +155 -0
- data/README.rd +53 -0
- data/Rakefile +21 -0
- data/lib/cache.rb +296 -0
- data/sample/filecache.rb +51 -0
- metadata +59 -0
data/Manual.rd
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
= Ruby/Cache Reference Manual
|
4
|
+
|
5
|
+
This is the reference manual for
|
6
|
+
((<"Ruby/Cache"|URL:http://www.nongnu.org/pupa/ruby-cache.html>)) version 0.3.
|
7
|
+
|
8
|
+
Ruby/Cache provides a class for caching arbitrary objects based on LRU
|
9
|
+
algorithm. The class (({Cache})) looks like a variant of (({Hash})), and,
|
10
|
+
in fact, (({Cache})) supports most of the methods of (({Hash})).
|
11
|
+
|
12
|
+
To control how to invalidate excessive objects, Ruby/Cache allows you to
|
13
|
+
adjust the limit by four factors: the size of an object, the total size
|
14
|
+
of objects, the number of objects, and a last access time.
|
15
|
+
|
16
|
+
== Class:
|
17
|
+
|
18
|
+
Cache
|
19
|
+
|
20
|
+
== Superclass:
|
21
|
+
|
22
|
+
Object
|
23
|
+
|
24
|
+
== Included module:
|
25
|
+
|
26
|
+
Enumerable
|
27
|
+
|
28
|
+
== Class methods:
|
29
|
+
|
30
|
+
--- Cache.version
|
31
|
+
Return the version number.
|
32
|
+
|
33
|
+
--- Cache.new([max_obj_size, max_size, max_num, expiration, &hook])
|
34
|
+
--- Cache.new(hash, &hook)
|
35
|
+
Create a new Cache object.
|
36
|
+
|
37
|
+
((|max_obj_size|)) is the maximum size per object allowed to be cached.
|
38
|
+
The size is currently determined by (({obj.to_s.size})).
|
39
|
+
|
40
|
+
((|max_size|)) is the maximum size of all objects allowed to be cached.
|
41
|
+
The size is currently determined by the sum of the sizes of all objects.
|
42
|
+
|
43
|
+
((|max_num|)) is the maximum number of cached objects.
|
44
|
+
|
45
|
+
((|expiration|)) is the maximum life time of each object after the last
|
46
|
+
access time, and is specified by seconds.
|
47
|
+
|
48
|
+
((|hook|)) is called whenever an object is invalidated, in the form
|
49
|
+
(({hook(key, value)})). So you can use ((|hook|)) for cleanups.
|
50
|
+
|
51
|
+
If the latter form is used, ((|hash|)) must be a Hash object, and it
|
52
|
+
represents keyword arguments. ((|hash|)) can have any combination of
|
53
|
+
these keys: (({:max_obj_size})), (({:max_size})), (({:max_num})) and
|
54
|
+
(({:expiration})). The meanings are the same as above.
|
55
|
+
|
56
|
+
== Methods:
|
57
|
+
|
58
|
+
--- max_obj_size
|
59
|
+
Return the maximum size per object.
|
60
|
+
|
61
|
+
--- max_size
|
62
|
+
Return the maximum size of all objects.
|
63
|
+
|
64
|
+
--- max_num
|
65
|
+
Return the maximum number of objects.
|
66
|
+
|
67
|
+
--- expiration
|
68
|
+
Return the maximum life time.
|
69
|
+
|
70
|
+
--- cached?(key)
|
71
|
+
--- include?(key)
|
72
|
+
--- member?(key)
|
73
|
+
--- key?(key)
|
74
|
+
--- has_key?(key)
|
75
|
+
Return (({true})), if the key ((|key|)) is cached.
|
76
|
+
|
77
|
+
--- cached_value?(val)
|
78
|
+
--- has_value?(val)
|
79
|
+
--- value?(val)
|
80
|
+
Return (({true})), if the value ((|val|)) is cached.
|
81
|
+
|
82
|
+
--- index(val)
|
83
|
+
Return the key corresponding to the value ((|val|)), if any. Otherwise
|
84
|
+
return (({nil})).
|
85
|
+
|
86
|
+
--- keys
|
87
|
+
Return an array of keys.
|
88
|
+
|
89
|
+
--- values
|
90
|
+
Return an array of cached objects.
|
91
|
+
|
92
|
+
--- length
|
93
|
+
--- size
|
94
|
+
Return the number of cached objects.
|
95
|
+
|
96
|
+
--- to_hash
|
97
|
+
Return keys and cached objects as a Hash object.
|
98
|
+
|
99
|
+
--- invalidate(key)
|
100
|
+
--- invalidate(key) {|key| ... }
|
101
|
+
--- delete(key)
|
102
|
+
--- delete(key) {|key| ... }
|
103
|
+
Invalidate a cached object indexed by the key ((|key|)), and return
|
104
|
+
the object. If the key isn't present, return (({nil})). If a block
|
105
|
+
is given and the key is invalid, evaluate the block and return the
|
106
|
+
result.
|
107
|
+
|
108
|
+
--- invalidate_all
|
109
|
+
--- clear
|
110
|
+
Invalidate all cached objects.
|
111
|
+
|
112
|
+
--- expire
|
113
|
+
Invalidate expired objects. This method is often called from other methods
|
114
|
+
automatically, so you wouldn't have to call it explicitly.
|
115
|
+
|
116
|
+
--- self[key]
|
117
|
+
Return a cached object corresponding to the key ((|key|)). If the key
|
118
|
+
isn't found, return (({nil})).
|
119
|
+
|
120
|
+
--- self[key]=value
|
121
|
+
--- store(key, value)
|
122
|
+
Cache the object ((|value|)) with the key ((|key|)), if possible.
|
123
|
+
Return ((|value|)).
|
124
|
+
|
125
|
+
--- each_pair {|key, obj| ... }
|
126
|
+
--- each {|key, obj| ... }
|
127
|
+
Evaluate the block with each key and a cached object corresponding to
|
128
|
+
the key.
|
129
|
+
|
130
|
+
--- each_key {|key| ... }
|
131
|
+
Evaluate the block with each key.
|
132
|
+
|
133
|
+
--- each_value {|obj| ... }
|
134
|
+
Evaluate the block with each cached object.
|
135
|
+
|
136
|
+
--- empty?
|
137
|
+
Return (({true})), if no object is cached.
|
138
|
+
|
139
|
+
--- fetch(key[, default])
|
140
|
+
--- fetch(key) {|key| ... }
|
141
|
+
Return a cached object corresponding to the key ((|key|)).
|
142
|
+
If the key isn't found and ((|default|)) is given, cache ((|default|))
|
143
|
+
as a object corresponding to ((|key|)) and return ((|default|)).
|
144
|
+
Or, if the key isn't found and a block is given, evaluate the block
|
145
|
+
with ((|key|)), cache the result, and return it.
|
146
|
+
|
147
|
+
Normally, you should use this method rather than (({self[key]})) plus
|
148
|
+
(({self[key]=value})), because this is safer.
|
149
|
+
|
150
|
+
--- statistics
|
151
|
+
Return an array of the total size of cached objects, the number of
|
152
|
+
cached objects, the number of cache hits, and the number of cache
|
153
|
+
misses.
|
154
|
+
|
155
|
+
=end
|
data/README.rd
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
=begin
|
2
|
+
= Ruby/Cache 0.3
|
3
|
+
== What is Ruby/Cache
|
4
|
+
|
5
|
+
Ruby/Cache is a library for caching objects based on the LRU algorithm
|
6
|
+
for Ruby. The official page is
|
7
|
+
((<URL:http://www.nongnu.org/pupa/ruby-cache.html>)).
|
8
|
+
|
9
|
+
== How to install
|
10
|
+
|
11
|
+
(1) $ ruby install.rb config
|
12
|
+
(2) $ ruby install.rb setup
|
13
|
+
(3) $ ruby install.rb install
|
14
|
+
|
15
|
+
== How to use
|
16
|
+
|
17
|
+
Here is a simple usage:
|
18
|
+
|
19
|
+
require 'cache'
|
20
|
+
|
21
|
+
cache = Cache.new
|
22
|
+
cache['foo'] = 'bar'
|
23
|
+
p cache['foo']
|
24
|
+
cache.invalidate('foo')
|
25
|
+
p cache['foo']
|
26
|
+
|
27
|
+
=>
|
28
|
+
|
29
|
+
"bar"
|
30
|
+
nil
|
31
|
+
|
32
|
+
This is a more complicated example:
|
33
|
+
|
34
|
+
# Set the maximum number of cached objects and the expiration time to
|
35
|
+
# 100 and 60 (secs), respectively.
|
36
|
+
cache = Cache.new(nil, nil, 100, 60)
|
37
|
+
puts 'I will generate a prime number greater than any given number!'
|
38
|
+
while true
|
39
|
+
puts 'Input an integer: '
|
40
|
+
i = gets.to_i
|
41
|
+
puts cache.fetch(i) { generate_prime_greater_than(i) }
|
42
|
+
end
|
43
|
+
|
44
|
+
== License
|
45
|
+
|
46
|
+
You may redistribute it and/or modify it under the same term as Ruby's.
|
47
|
+
|
48
|
+
== Author
|
49
|
+
|
50
|
+
((<Yoshinori K. Okuji|URL:http://www.enbug.org/>))
|
51
|
+
((<<okuji@enbug.org>|URL:mailto:okuji@enbug.org>))
|
52
|
+
|
53
|
+
=end
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake/gempackagetask'
|
3
|
+
|
4
|
+
spec = Gem::Specification.new do |s|
|
5
|
+
s.name = "ruby-cache"
|
6
|
+
s.version = "0.3.0"
|
7
|
+
s.summary = "Ruby/Cache is a library for caching objects based on the LRU algorithm for Ruby"
|
8
|
+
s.author = "Yoshinori K. Okuji"
|
9
|
+
s.email = "okuji@enbug.org"
|
10
|
+
s.homepage = "http://www.enbug.org/"
|
11
|
+
s.description = s.summary
|
12
|
+
s.rubyforge_project = "N/A"
|
13
|
+
s.has_rdoc = true
|
14
|
+
files = Dir.glob("{lib,sample}/*")
|
15
|
+
files << 'README.rd' << 'Manual.rd' << 'Rakefile'
|
16
|
+
s.files = files
|
17
|
+
end
|
18
|
+
|
19
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
20
|
+
pkg.need_zip = true
|
21
|
+
end
|
data/lib/cache.rb
ADDED
@@ -0,0 +1,296 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
|
4
|
+
#
|
5
|
+
# You may redistribute it and/or modify it under the same term as Ruby.
|
6
|
+
|
7
|
+
# Cache manager based on the LRU algorithm.
|
8
|
+
class Cache
|
9
|
+
|
10
|
+
CACHE_OBJECT = Struct.new('CacheObject', :content, :size, :atime)
|
11
|
+
CACHE_VERSION = '0.3'
|
12
|
+
|
13
|
+
include Enumerable
|
14
|
+
|
15
|
+
def self.version
|
16
|
+
CACHE_VERSION
|
17
|
+
end
|
18
|
+
|
19
|
+
# initialize(max_obj_size = nil, max_size = nil, max_num = nil,
|
20
|
+
# expiration = nil, &hook)
|
21
|
+
# initialize(hash, &hook)
|
22
|
+
def initialize(*args, &hook)
|
23
|
+
if args.size == 1 and args[0].kind_of?(Hash)
|
24
|
+
@max_obj_size = @max_size = @max_num = @expiration = nil
|
25
|
+
args[0].each do |k, v|
|
26
|
+
k = k.intern if k.respond_to?(:intern)
|
27
|
+
case k
|
28
|
+
when :max_obj_size
|
29
|
+
@max_obj_size = v
|
30
|
+
when :max_size
|
31
|
+
@max_size = v
|
32
|
+
when :max_num
|
33
|
+
@max_num = v
|
34
|
+
when :expiration
|
35
|
+
@expiration = v
|
36
|
+
end
|
37
|
+
end
|
38
|
+
else
|
39
|
+
@max_obj_size, @max_size, @max_num, @expiration = args
|
40
|
+
end
|
41
|
+
|
42
|
+
# Sanity checks.
|
43
|
+
if @max_obj_size and @max_size and @max_obj_size > @max_size
|
44
|
+
raise ArgumentError, "max_obj_size exceeds max_size (#{@max_obj_size} > #{@max_size})"
|
45
|
+
end
|
46
|
+
if @max_obj_size and @max_obj_size <= 0
|
47
|
+
raise ArgumentError, "invalid max_obj_size `#{@max_obj_size}'"
|
48
|
+
end
|
49
|
+
if @max_size and @max_size <= 0
|
50
|
+
raise ArgumentError, "invalid max_size `#{@max_size}'"
|
51
|
+
end
|
52
|
+
if @max_num and @max_num <= 0
|
53
|
+
raise ArgumentError, "invalid max_num `#{@max_num}'"
|
54
|
+
end
|
55
|
+
if @expiration and @expiration <= 0
|
56
|
+
raise ArgumentError, "invalid expiration `#{@expiration}'"
|
57
|
+
end
|
58
|
+
|
59
|
+
@hook = hook
|
60
|
+
|
61
|
+
@objs = {}
|
62
|
+
@size = 0
|
63
|
+
@list = []
|
64
|
+
|
65
|
+
@hits = 0
|
66
|
+
@misses = 0
|
67
|
+
end
|
68
|
+
|
69
|
+
attr_reader :max_obj_size, :max_size, :max_num, :expiration
|
70
|
+
|
71
|
+
def cached?(key)
|
72
|
+
@objs.include?(key)
|
73
|
+
end
|
74
|
+
alias :include? :cached?
|
75
|
+
alias :member? :cached?
|
76
|
+
alias :key? :cached?
|
77
|
+
alias :has_key? :cached?
|
78
|
+
|
79
|
+
def cached_value?(val)
|
80
|
+
self.each_value do |v|
|
81
|
+
return true if v == val
|
82
|
+
end
|
83
|
+
false
|
84
|
+
end
|
85
|
+
alias :has_value? :cached_value?
|
86
|
+
alias :value? :cached_value?
|
87
|
+
|
88
|
+
def index(val)
|
89
|
+
self.each_pair do |k,v|
|
90
|
+
return k if v == val
|
91
|
+
end
|
92
|
+
nil
|
93
|
+
end
|
94
|
+
|
95
|
+
def keys
|
96
|
+
@objs.keys
|
97
|
+
end
|
98
|
+
|
99
|
+
def length
|
100
|
+
@objs.length
|
101
|
+
end
|
102
|
+
alias :size :length
|
103
|
+
|
104
|
+
def to_hash
|
105
|
+
@objs.dup
|
106
|
+
end
|
107
|
+
|
108
|
+
def values
|
109
|
+
@objs.collect {|key, obj| obj.content}
|
110
|
+
end
|
111
|
+
|
112
|
+
def invalidate(key)
|
113
|
+
obj = @objs[key]
|
114
|
+
if obj
|
115
|
+
if @hook
|
116
|
+
@hook.call(key, obj.content)
|
117
|
+
end
|
118
|
+
@size -= obj.size
|
119
|
+
@objs.delete(key)
|
120
|
+
@list.each_index do |i|
|
121
|
+
if @list[i] == key
|
122
|
+
@list.delete_at(i)
|
123
|
+
break
|
124
|
+
end
|
125
|
+
end
|
126
|
+
elsif block_given?
|
127
|
+
return yield(key)
|
128
|
+
end
|
129
|
+
obj.content
|
130
|
+
end
|
131
|
+
alias :delete :invalidate
|
132
|
+
|
133
|
+
def invalidate_all()
|
134
|
+
if @hook
|
135
|
+
@objs.each do |key, obj|
|
136
|
+
@hook.call(key, obj)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
@objs.clear
|
141
|
+
@list.clear
|
142
|
+
@size = 0
|
143
|
+
end
|
144
|
+
alias :clear :invalidate_all
|
145
|
+
|
146
|
+
def expire()
|
147
|
+
if @expiration
|
148
|
+
now = Time.now.to_i
|
149
|
+
@list.each_index do |i|
|
150
|
+
key = @list[i]
|
151
|
+
|
152
|
+
break unless @objs[key].atime + @expiration <= now
|
153
|
+
self.invalidate(key)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
# GC.start
|
157
|
+
end
|
158
|
+
|
159
|
+
def [](key)
|
160
|
+
self.expire()
|
161
|
+
|
162
|
+
unless @objs.include?(key)
|
163
|
+
@misses += 1
|
164
|
+
return nil
|
165
|
+
end
|
166
|
+
|
167
|
+
obj = @objs[key]
|
168
|
+
obj.atime = Time.now.to_i
|
169
|
+
|
170
|
+
@list.each_index do |i|
|
171
|
+
if @list[i] == key
|
172
|
+
@list.delete_at(i)
|
173
|
+
break
|
174
|
+
end
|
175
|
+
end
|
176
|
+
@list.push(key)
|
177
|
+
|
178
|
+
@hits += 1
|
179
|
+
obj.content
|
180
|
+
end
|
181
|
+
|
182
|
+
def []=(key, obj)
|
183
|
+
self.expire()
|
184
|
+
|
185
|
+
if self.cached?(key)
|
186
|
+
self.invalidate(key)
|
187
|
+
end
|
188
|
+
|
189
|
+
size = obj.to_s.size
|
190
|
+
if @max_obj_size and @max_obj_size < size
|
191
|
+
if $DEBUG
|
192
|
+
$stderr.puts("warning: `#{obj.inspect}' isn't cached because its size exceeds #{@max_obj_size}")
|
193
|
+
end
|
194
|
+
return obj
|
195
|
+
end
|
196
|
+
if @max_obj_size.nil? and @max_size and @max_size < size
|
197
|
+
if $DEBUG
|
198
|
+
$stderr.puts("warning: `#{obj.inspect}' isn't cached because its size exceeds #{@max_size}")
|
199
|
+
end
|
200
|
+
return obj
|
201
|
+
end
|
202
|
+
|
203
|
+
if @max_num and @max_num == @list.size
|
204
|
+
self.invalidate(@list.first)
|
205
|
+
end
|
206
|
+
|
207
|
+
@size += size
|
208
|
+
if @max_size
|
209
|
+
while @max_size < @size
|
210
|
+
self.invalidate(@list.first)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
@objs[key] = CACHE_OBJECT.new(obj, size, Time.now.to_i)
|
215
|
+
@list.push(key)
|
216
|
+
|
217
|
+
obj
|
218
|
+
end
|
219
|
+
|
220
|
+
def store(key, value)
|
221
|
+
self[key] = value
|
222
|
+
end
|
223
|
+
|
224
|
+
def each_pair
|
225
|
+
@objs.each do |key, obj|
|
226
|
+
yield key, obj.content
|
227
|
+
end
|
228
|
+
self
|
229
|
+
end
|
230
|
+
alias :each :each_pair
|
231
|
+
|
232
|
+
def each_key
|
233
|
+
@objs.each_key do |key|
|
234
|
+
yield key
|
235
|
+
end
|
236
|
+
self
|
237
|
+
end
|
238
|
+
|
239
|
+
def each_value
|
240
|
+
@objs.each_value do |obj|
|
241
|
+
yield obj.content
|
242
|
+
end
|
243
|
+
self
|
244
|
+
end
|
245
|
+
|
246
|
+
def empty?
|
247
|
+
@objs.empty?
|
248
|
+
end
|
249
|
+
|
250
|
+
def fetch(key, default = nil)
|
251
|
+
val = self[key]
|
252
|
+
if val.nil?
|
253
|
+
if default
|
254
|
+
val = self[key] = default
|
255
|
+
elsif block_given?
|
256
|
+
val = self[key] = yield(key)
|
257
|
+
else
|
258
|
+
raise IndexError, "invalid key `#{key}'"
|
259
|
+
end
|
260
|
+
end
|
261
|
+
val
|
262
|
+
end
|
263
|
+
|
264
|
+
# The total size of cached objects, the number of cached objects,
|
265
|
+
# the number of cache hits, and the number of cache misses.
|
266
|
+
def statistics()
|
267
|
+
[@size, @list.size, @hits, @misses]
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
# Run a test, if executed.
|
272
|
+
if __FILE__ == $0
|
273
|
+
cache = Cache.new(100 * 1024, 100 * 1024 * 1024, 256, 1)
|
274
|
+
1000.times do
|
275
|
+
key = rand(1000)
|
276
|
+
cache[key] = key.to_s
|
277
|
+
end
|
278
|
+
1000.times do
|
279
|
+
key = rand(1000)
|
280
|
+
puts cache[key]
|
281
|
+
end
|
282
|
+
sleep 1
|
283
|
+
1000.times do
|
284
|
+
key = rand(1000)
|
285
|
+
puts cache[key]
|
286
|
+
end
|
287
|
+
|
288
|
+
stat = cache.statistics()
|
289
|
+
hits = stat[2]
|
290
|
+
misses = stat[3]
|
291
|
+
ratio = hits.to_f / (hits + misses)
|
292
|
+
|
293
|
+
puts "Total size:\t#{stat[0]}"
|
294
|
+
puts "Number:\t\t#{stat[1]}"
|
295
|
+
puts "Hit ratio:\t#{ratio * 100}% (#{hits} / #{hits + misses})"
|
296
|
+
end
|
data/sample/filecache.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# Copyright (C) 2002 Koji Arai
|
2
|
+
# Copyright (C) 2002 Yoshinori K. Okuji
|
3
|
+
#
|
4
|
+
# You may redistribute it and/or modify it under the same term as Ruby.
|
5
|
+
|
6
|
+
require 'cache'
|
7
|
+
|
8
|
+
class FileCache
|
9
|
+
def initialize(maxopen = 10)
|
10
|
+
@cache = Cache.new(:max_num => maxopen) {|key, obj| obj.close}
|
11
|
+
@saw = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def open(file)
|
15
|
+
@cache.fetch(file) do
|
16
|
+
mode = if @saw.key?(file) then 'a' else 'w' end
|
17
|
+
@saw[file] = true
|
18
|
+
File.open(file, mode)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def close
|
23
|
+
@cache.invalidate_all
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
if $0 == __FILE__
|
28
|
+
File.open("/tmp/foo", "w") {|f|
|
29
|
+
1000.times {|i|
|
30
|
+
f.printf("file%03d %d\n", rand(100), i)
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
# /tmp/foo
|
35
|
+
# foo001 0
|
36
|
+
# foo099 1
|
37
|
+
# foo050 2
|
38
|
+
# foo001 3
|
39
|
+
# :
|
40
|
+
# :
|
41
|
+
|
42
|
+
cacheout = FileCache.new(10)
|
43
|
+
|
44
|
+
File.open("/tmp/foo") {|f|
|
45
|
+
while line = f.gets
|
46
|
+
file, number = line.split
|
47
|
+
|
48
|
+
cacheout.open(file).puts number
|
49
|
+
end
|
50
|
+
}
|
51
|
+
end
|
metadata
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ruby-cache
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Yoshinori K. Okuji
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-11-21 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Ruby/Cache is a library for caching objects based on the LRU algorithm for Ruby
|
17
|
+
email: okuji@enbug.org
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- lib/cache.rb
|
26
|
+
- sample/filecache.rb
|
27
|
+
- README.rd
|
28
|
+
- Manual.rd
|
29
|
+
- Rakefile
|
30
|
+
has_rdoc: true
|
31
|
+
homepage: http://www.enbug.org/
|
32
|
+
licenses: []
|
33
|
+
|
34
|
+
post_install_message:
|
35
|
+
rdoc_options: []
|
36
|
+
|
37
|
+
require_paths:
|
38
|
+
- lib
|
39
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: "0"
|
44
|
+
version:
|
45
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: "0"
|
50
|
+
version:
|
51
|
+
requirements: []
|
52
|
+
|
53
|
+
rubyforge_project: N/A
|
54
|
+
rubygems_version: 1.3.5
|
55
|
+
signing_key:
|
56
|
+
specification_version: 3
|
57
|
+
summary: Ruby/Cache is a library for caching objects based on the LRU algorithm for Ruby
|
58
|
+
test_files: []
|
59
|
+
|