upload_cache 1.0.0 → 1.2.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/lib/upload_cache.rb +152 -60
- data/upload_cache.gemspec +28 -0
- metadata +29 -52
data/lib/upload_cache.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
|
-
require 'uuidtools'
|
2
1
|
require 'fileutils'
|
3
2
|
require 'cgi'
|
3
|
+
require 'tmpdir'
|
4
|
+
|
5
|
+
require 'map'
|
4
6
|
|
5
7
|
class UploadCache
|
6
|
-
Version = '1.
|
8
|
+
Version = '1.2.0'
|
7
9
|
|
8
|
-
|
10
|
+
Readme = <<-__
|
9
11
|
NAME
|
10
12
|
upload_cache.rb
|
11
13
|
|
@@ -49,6 +51,9 @@ class UploadCache
|
|
49
51
|
|
50
52
|
UploadCache.clear! ### nuke old files once per day
|
51
53
|
|
54
|
+
upload_caches ***does this automatically*** at_exit{}, but you can still
|
55
|
+
run it manually if you like.
|
56
|
+
|
52
57
|
__
|
53
58
|
|
54
59
|
class << UploadCache
|
@@ -56,25 +61,36 @@ class UploadCache
|
|
56
61
|
UploadCache::Version
|
57
62
|
end
|
58
63
|
|
59
|
-
def
|
60
|
-
@
|
64
|
+
def url
|
65
|
+
@url ||= "file:/#{ root }"
|
61
66
|
end
|
62
67
|
|
63
|
-
def
|
64
|
-
@
|
68
|
+
def url=(url)
|
69
|
+
@url = '/' + Array(url).join('/').squeeze('/').sub(%r|^/+|, '').sub(%r|/+$|, '')
|
65
70
|
end
|
66
71
|
|
67
|
-
def
|
68
|
-
|
72
|
+
def root
|
73
|
+
@root ||= Dir.tmpdir
|
69
74
|
end
|
70
75
|
|
71
|
-
def root
|
72
|
-
@root
|
76
|
+
def root=(root)
|
77
|
+
@root = File.expand_path(root)
|
73
78
|
end
|
74
79
|
|
75
|
-
|
76
|
-
|
80
|
+
{
|
81
|
+
'ffi-uuid' => proc{|*args| FFI::UUID.generate_time.to_s},
|
82
|
+
'uuid' => proc{|*args| UUID.generate.to_s},
|
83
|
+
'uuidtools' => proc{|*args| UUIDTools::UUID.timestamp_create.to_s}
|
84
|
+
}.each do |lib, implementation|
|
85
|
+
begin
|
86
|
+
require(lib)
|
87
|
+
define_method(:uuid, &implementation)
|
88
|
+
break
|
89
|
+
rescue LoadError
|
90
|
+
nil
|
91
|
+
end
|
77
92
|
end
|
93
|
+
abort 'no suitable uuid generation library detected' unless method_defined?(:uuid)
|
78
94
|
|
79
95
|
def tmpdir(&block)
|
80
96
|
tmpdir = File.join(root, uuid)
|
@@ -93,35 +109,9 @@ class UploadCache
|
|
93
109
|
end
|
94
110
|
|
95
111
|
def cache_key_for(key)
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
def for(params, key = :upload)
|
100
|
-
upload = params[key]
|
101
|
-
if upload.respond_to?(:read)
|
102
|
-
tmpdir do |tmp|
|
103
|
-
original_basename = upload.respond_to?(:original_path) ? upload.original_path : upload.original_filename
|
104
|
-
basename = cleanname(original_basename)
|
105
|
-
|
106
|
-
path = File.join(tmp, basename)
|
107
|
-
open(path, 'w'){|fd| fd.write(upload.read)}
|
108
|
-
upload_cache = new(key, path)
|
109
|
-
params[key] = upload_cache.io
|
110
|
-
return upload_cache
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
cache_key = cache_key_for(key)
|
115
|
-
upload_cache = params[cache_key]
|
116
|
-
if upload_cache
|
117
|
-
dirname, basename = File.split(upload_cache)
|
118
|
-
path = root + '/' + File.join(File.basename(dirname), basename)
|
119
|
-
upload_cache = new(key, path)
|
120
|
-
params[key] = upload_cache.io
|
121
|
-
return upload_cache
|
112
|
+
key.clone.tap do |cache_key|
|
113
|
+
cache_key[-1] = "#{ cache_key[-1] }_upload_cache"
|
122
114
|
end
|
123
|
-
|
124
|
-
return new(key, path=nil)
|
125
115
|
end
|
126
116
|
|
127
117
|
def finalizer(object_id)
|
@@ -135,6 +125,8 @@ class UploadCache
|
|
135
125
|
Age = 60 * 60 * 24
|
136
126
|
|
137
127
|
def clear!(options = {})
|
128
|
+
return if UploadCache.turd?
|
129
|
+
|
138
130
|
glob = File.join(root, '*')
|
139
131
|
age = Integer(options[:age] || options['age'] || Age)
|
140
132
|
since = options[:since] || options['since'] || Time.now
|
@@ -163,47 +155,136 @@ class UploadCache
|
|
163
155
|
end
|
164
156
|
end
|
165
157
|
end
|
158
|
+
|
159
|
+
at_exit{ UploadCache.clear! }
|
160
|
+
|
161
|
+
def turd?
|
162
|
+
@turd ||= !!ENV['UPLOAD_CACHE_TURD']
|
163
|
+
end
|
164
|
+
|
165
|
+
def name_for(key, &block)
|
166
|
+
if block
|
167
|
+
@name_for = block
|
168
|
+
else
|
169
|
+
defined?(@name_for) ? @name_for[key] : [prefix, *Array(key)].compact.join('.')
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def prefix(*value)
|
174
|
+
@prefix = value.shift if value
|
175
|
+
@prefix
|
176
|
+
end
|
177
|
+
|
178
|
+
def prefix=(value)
|
179
|
+
@prefix = value
|
180
|
+
end
|
181
|
+
|
182
|
+
def default
|
183
|
+
@default ||= Map[:url, nil, :path, nil]
|
184
|
+
end
|
185
|
+
|
186
|
+
def for(params, *args)
|
187
|
+
params = Map.for(params)
|
188
|
+
options = Map.options_for!(args)
|
189
|
+
|
190
|
+
key = Array(options[:key] || args).flatten.compact
|
191
|
+
key = [:upload] if key.empty?
|
192
|
+
|
193
|
+
upload = params.get(key)
|
194
|
+
|
195
|
+
if upload.respond_to?(:read)
|
196
|
+
tmpdir do |tmp|
|
197
|
+
original_basename =
|
198
|
+
[:path, :filename, :original_path, :original_filename].
|
199
|
+
map{|msg| upload.send(msg) if upload.respond_to?(msg)}.compact.first
|
200
|
+
basename = cleanname(original_basename)
|
201
|
+
|
202
|
+
path = File.join(tmp, basename)
|
203
|
+
open(path, 'wb'){|fd| fd.write(upload.read)}
|
204
|
+
upload_cache = UploadCache.new(key, path, options)
|
205
|
+
params.set(key, upload_cache.io)
|
206
|
+
return upload_cache
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
cache_key = cache_key_for(key)
|
211
|
+
upload_cache = params.get(cache_key)
|
212
|
+
|
213
|
+
if upload_cache
|
214
|
+
dirname, basename = File.split(upload_cache)
|
215
|
+
relative_dirname = File.expand_path(File.dirname(dirname))
|
216
|
+
relative_basename = File.join(relative_dirname, basename)
|
217
|
+
path = root + '/' + relative_basename
|
218
|
+
upload_cache = UploadCache.new(key, path, options)
|
219
|
+
params.set(key, upload_cache.io)
|
220
|
+
return upload_cache
|
221
|
+
end
|
222
|
+
|
223
|
+
upload_cache = UploadCache.new(key, options)
|
224
|
+
params.set(key, upload_cache.io) if upload_cache.io
|
225
|
+
return upload_cache
|
226
|
+
end
|
166
227
|
end
|
167
228
|
|
168
229
|
attr_accessor :key
|
169
230
|
attr_accessor :cache_key
|
231
|
+
attr_accessor :name
|
170
232
|
attr_accessor :path
|
171
233
|
attr_accessor :dirname
|
172
234
|
attr_accessor :basename
|
173
235
|
attr_accessor :value
|
174
236
|
attr_accessor :io
|
237
|
+
attr_accessor :default_url
|
238
|
+
attr_accessor :default_path
|
175
239
|
|
176
240
|
IOs = {}
|
177
241
|
|
178
|
-
def initialize(key,
|
179
|
-
|
180
|
-
|
242
|
+
def initialize(key, *args)
|
243
|
+
options = Map.options_for!(args)
|
244
|
+
|
245
|
+
@key = key
|
246
|
+
@cache_key = UploadCache.cache_key_for(@key)
|
247
|
+
@name = UploadCache.name_for(@cache_key)
|
248
|
+
|
249
|
+
path = args.shift || options[:path]
|
250
|
+
|
251
|
+
default = Map.for(options[:default])
|
252
|
+
|
253
|
+
@default_url = default[:url] || options[:default_url] || UploadCache.default.url
|
254
|
+
@default_path = default[:path] || options[:default_path] || UploadCache.default.path
|
181
255
|
|
182
256
|
if path
|
183
257
|
@path = path
|
184
258
|
@dirname, @basename = File.split(@path)
|
185
259
|
@value = File.join(File.basename(@dirname), @basename).strip
|
186
|
-
@io = open(@path)
|
187
|
-
IOs[object_id] = @io.fileno
|
188
|
-
ObjectSpace.define_finalizer(self, UploadCache.method(:finalizer).to_proc)
|
189
260
|
else
|
190
261
|
@path = nil
|
191
262
|
@value = nil
|
192
263
|
end
|
264
|
+
|
265
|
+
if @path or @default_path
|
266
|
+
@io = open(@path || @default_path, 'rb')
|
267
|
+
IOs[object_id] = @io.fileno
|
268
|
+
ObjectSpace.define_finalizer(self, UploadCache.method(:finalizer).to_proc)
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
def url
|
273
|
+
if @value
|
274
|
+
File.join(UploadCache.url, @value)
|
275
|
+
else
|
276
|
+
@default_url ? @default_url : nil
|
277
|
+
end
|
193
278
|
end
|
194
279
|
|
195
280
|
def hidden
|
196
|
-
raw("<input type='hidden' name='#{ @
|
281
|
+
raw("<input type='hidden' name='#{ @name }' value='#{ @value }' class='upload_cache' />") if @value
|
197
282
|
end
|
198
283
|
|
199
284
|
def to_s
|
200
285
|
hidden.to_s
|
201
286
|
end
|
202
287
|
|
203
|
-
def url
|
204
|
-
File.join(UploadCache.url, @value) if @value
|
205
|
-
end
|
206
|
-
|
207
288
|
module HtmlSafe
|
208
289
|
def html_safe() self end
|
209
290
|
def html_safe?() self end
|
@@ -218,23 +299,34 @@ class UploadCache
|
|
218
299
|
end
|
219
300
|
|
220
301
|
def clear!
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
302
|
+
return if UploadCache.turd?
|
303
|
+
|
304
|
+
begin
|
305
|
+
FileUtils.rm_rf(@dirname) if test(?d, @dirname)
|
306
|
+
rescue
|
307
|
+
nil
|
308
|
+
ensure
|
309
|
+
@io.close rescue nil
|
310
|
+
IOs.delete(object_id)
|
311
|
+
Thread.new{ UploadCache.clear! }
|
312
|
+
end
|
228
313
|
end
|
229
314
|
end
|
230
315
|
|
231
316
|
Upload_cache = UploadCache unless defined?(Upload_cache)
|
232
317
|
|
318
|
+
|
319
|
+
|
233
320
|
if defined?(Rails.env)
|
321
|
+
|
322
|
+
if defined?(Rails.root) and Rails.root
|
323
|
+
UploadCache.url = '/system/uploads/cache'
|
324
|
+
UploadCache.root = File.join(Rails.root, 'public', UploadCache.url)
|
325
|
+
end
|
326
|
+
|
234
327
|
unless Rails.env.production?
|
235
328
|
if defined?(unloadable)
|
236
329
|
unloadable(UploadCache)
|
237
|
-
unloadable(Upload_cache)
|
238
330
|
end
|
239
331
|
end
|
240
332
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
## upload_cache.gemspec
|
2
|
+
#
|
3
|
+
|
4
|
+
Gem::Specification::new do |spec|
|
5
|
+
spec.name = "upload_cache"
|
6
|
+
spec.version = "1.2.0"
|
7
|
+
spec.platform = Gem::Platform::RUBY
|
8
|
+
spec.summary = "upload_cache"
|
9
|
+
spec.description = "description: upload_cache kicks the ass"
|
10
|
+
|
11
|
+
spec.files = ["lib", "lib/upload_cache.rb", "Rakefile", "README", "upload_cache.gemspec"]
|
12
|
+
spec.executables = []
|
13
|
+
|
14
|
+
spec.require_path = "lib"
|
15
|
+
|
16
|
+
spec.has_rdoc = true
|
17
|
+
spec.test_files = nil
|
18
|
+
|
19
|
+
# spec.add_dependency 'lib', '>= version'
|
20
|
+
spec.add_dependency 'uuidtools'
|
21
|
+
|
22
|
+
spec.extensions.push(*[])
|
23
|
+
|
24
|
+
spec.rubyforge_project = "codeforpeople"
|
25
|
+
spec.author = "Ara T. Howard"
|
26
|
+
spec.email = "ara.t.howard@gmail.com"
|
27
|
+
spec.homepage = "http://github.com/ahoward/upload_cache"
|
28
|
+
end
|
metadata
CHANGED
@@ -1,82 +1,59 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: upload_cache
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.2.0
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 1
|
8
|
-
- 0
|
9
|
-
- 0
|
10
|
-
version: 1.0.0
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Ara T. Howard
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
dependencies:
|
21
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2011-12-02 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
22
15
|
name: uuidtools
|
23
|
-
|
24
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
16
|
+
requirement: &70226716783500 !ruby/object:Gem::Requirement
|
25
17
|
none: false
|
26
|
-
requirements:
|
27
|
-
- -
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
|
30
|
-
segments:
|
31
|
-
- 0
|
32
|
-
version: "0"
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
33
22
|
type: :runtime
|
34
|
-
|
35
|
-
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70226716783500
|
25
|
+
description: ! 'description: upload_cache kicks the ass'
|
36
26
|
email: ara.t.howard@gmail.com
|
37
27
|
executables: []
|
38
|
-
|
39
28
|
extensions: []
|
40
|
-
|
41
29
|
extra_rdoc_files: []
|
42
|
-
|
43
|
-
files:
|
30
|
+
files:
|
44
31
|
- lib/upload_cache.rb
|
45
32
|
- Rakefile
|
46
33
|
- README
|
47
|
-
|
34
|
+
- upload_cache.gemspec
|
48
35
|
homepage: http://github.com/ahoward/upload_cache
|
49
36
|
licenses: []
|
50
|
-
|
51
37
|
post_install_message:
|
52
38
|
rdoc_options: []
|
53
|
-
|
54
|
-
require_paths:
|
39
|
+
require_paths:
|
55
40
|
- lib
|
56
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
41
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
57
42
|
none: false
|
58
|
-
requirements:
|
59
|
-
- -
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
|
62
|
-
|
63
|
-
- 0
|
64
|
-
version: "0"
|
65
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
48
|
none: false
|
67
|
-
requirements:
|
68
|
-
- -
|
69
|
-
- !ruby/object:Gem::Version
|
70
|
-
|
71
|
-
segments:
|
72
|
-
- 0
|
73
|
-
version: "0"
|
49
|
+
requirements:
|
50
|
+
- - ! '>='
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
74
53
|
requirements: []
|
75
|
-
|
76
54
|
rubyforge_project: codeforpeople
|
77
|
-
rubygems_version: 1.
|
55
|
+
rubygems_version: 1.8.11
|
78
56
|
signing_key:
|
79
57
|
specification_version: 3
|
80
58
|
summary: upload_cache
|
81
59
|
test_files: []
|
82
|
-
|