upload_cache 1.0.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/README +42 -0
- data/Rakefile +365 -0
- data/lib/upload_cache.rb +240 -0
- metadata +82 -0
data/README
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
NAME
|
|
2
|
+
upload_cache.rb
|
|
3
|
+
|
|
4
|
+
DESCRIPTION
|
|
5
|
+
a small utility library to facility caching http file uploads between
|
|
6
|
+
form validation failures. designed for rails, but usable anywhere.
|
|
7
|
+
|
|
8
|
+
USAGE
|
|
9
|
+
in the controller
|
|
10
|
+
|
|
11
|
+
def upload
|
|
12
|
+
@upload_cache = UploadCache.for(params, :upload)
|
|
13
|
+
|
|
14
|
+
@record = Model.new(params)
|
|
15
|
+
|
|
16
|
+
if request.get?
|
|
17
|
+
render and return
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
if request.post?
|
|
21
|
+
@record.save!
|
|
22
|
+
@upload_cache.clear!
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
in the view
|
|
28
|
+
|
|
29
|
+
<input type='file' name='upload />
|
|
30
|
+
|
|
31
|
+
<%= @upload_cache.hidden %>
|
|
32
|
+
|
|
33
|
+
<!-- optionally, you can show any uploaded upload -->
|
|
34
|
+
|
|
35
|
+
<% if url = @upload_cache.url %>
|
|
36
|
+
you already uploaded: <img src='<%= raw url %>' />
|
|
37
|
+
<% end %>
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
in a rake task
|
|
41
|
+
|
|
42
|
+
UploadCache.clear! ### nuke old files once per day
|
data/Rakefile
ADDED
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
This.rubyforge_project = 'codeforpeople'
|
|
2
|
+
This.author = "Ara T. Howard"
|
|
3
|
+
This.email = "ara.t.howard@gmail.com"
|
|
4
|
+
This.homepage = "http://github.com/ahoward/#{ This.lib }"
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
task :default do
|
|
8
|
+
puts((Rake::Task.tasks.map{|task| task.name.gsub(/::/,':')} - ['default']).sort)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
task :test do
|
|
12
|
+
run_tests!
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
namespace :test do
|
|
16
|
+
task(:unit){ run_tests!(:unit) }
|
|
17
|
+
task(:functional){ run_tests!(:functional) }
|
|
18
|
+
task(:integration){ run_tests!(:integration) }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def run_tests!(which = nil)
|
|
22
|
+
which ||= '**'
|
|
23
|
+
test_dir = File.join(This.dir, "test")
|
|
24
|
+
test_glob ||= File.join(test_dir, "#{ which }/**_test.rb")
|
|
25
|
+
test_rbs = Dir.glob(test_glob).sort
|
|
26
|
+
|
|
27
|
+
div = ('=' * 119)
|
|
28
|
+
line = ('-' * 119)
|
|
29
|
+
helper = "-r ./test/helper.rb" if test(?e, "./test/helper.rb")
|
|
30
|
+
|
|
31
|
+
test_rbs.each_with_index do |test_rb, index|
|
|
32
|
+
testno = index + 1
|
|
33
|
+
command = "#{ This.ruby } -I ./lib -I ./test/lib #{ helper } #{ test_rb }"
|
|
34
|
+
|
|
35
|
+
puts
|
|
36
|
+
say(div, :color => :cyan, :bold => true)
|
|
37
|
+
say("@#{ testno } => ", :bold => true, :method => :print)
|
|
38
|
+
say(command, :color => :cyan, :bold => true)
|
|
39
|
+
say(line, :color => :cyan, :bold => true)
|
|
40
|
+
|
|
41
|
+
system(command)
|
|
42
|
+
|
|
43
|
+
say(line, :color => :cyan, :bold => true)
|
|
44
|
+
|
|
45
|
+
status = $?.exitstatus
|
|
46
|
+
|
|
47
|
+
if status.zero?
|
|
48
|
+
say("@#{ testno } <= ", :bold => true, :color => :white, :method => :print)
|
|
49
|
+
say("SUCCESS", :color => :green, :bold => true)
|
|
50
|
+
else
|
|
51
|
+
say("@#{ testno } <= ", :bold => true, :color => :white, :method => :print)
|
|
52
|
+
say("FAILURE", :color => :red, :bold => true)
|
|
53
|
+
end
|
|
54
|
+
say(line, :color => :cyan, :bold => true)
|
|
55
|
+
|
|
56
|
+
exit(status) unless status.zero?
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
task :gemspec do
|
|
62
|
+
ignore_extensions = 'git', 'svn', 'tmp', /sw./, 'bak', 'gem'
|
|
63
|
+
ignore_directories = %w[ pkg ]
|
|
64
|
+
ignore_files = %w[ test/log ]
|
|
65
|
+
|
|
66
|
+
shiteless =
|
|
67
|
+
lambda do |list|
|
|
68
|
+
list.delete_if do |entry|
|
|
69
|
+
next unless test(?e, entry)
|
|
70
|
+
extension = File.basename(entry).split(%r/[.]/).last
|
|
71
|
+
ignore_extensions.any?{|ext| ext === extension}
|
|
72
|
+
end
|
|
73
|
+
list.delete_if do |entry|
|
|
74
|
+
next unless test(?d, entry)
|
|
75
|
+
dirname = File.expand_path(entry)
|
|
76
|
+
ignore_directories.any?{|dir| File.expand_path(dir) == dirname}
|
|
77
|
+
end
|
|
78
|
+
list.delete_if do |entry|
|
|
79
|
+
next unless test(?f, entry)
|
|
80
|
+
filename = File.expand_path(entry)
|
|
81
|
+
ignore_files.any?{|file| File.expand_path(file) == filename}
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
lib = This.lib
|
|
86
|
+
object = This.object
|
|
87
|
+
version = This.version
|
|
88
|
+
files = shiteless[Dir::glob("**/**")]
|
|
89
|
+
executables = shiteless[Dir::glob("bin/*")].map{|exe| File.basename(exe)}
|
|
90
|
+
has_rdoc = true #File.exist?('doc')
|
|
91
|
+
test_files = "test/#{ lib }.rb" if File.file?("test/#{ lib }.rb")
|
|
92
|
+
summary = object.respond_to?(:summary) ? object.summary : "summary: #{ lib } kicks the ass"
|
|
93
|
+
description = object.respond_to?(:description) ? object.description : "description: #{ lib } kicks the ass"
|
|
94
|
+
|
|
95
|
+
if This.extensions.nil?
|
|
96
|
+
This.extensions = []
|
|
97
|
+
extensions = This.extensions
|
|
98
|
+
%w( Makefile configure extconf.rb ).each do |ext|
|
|
99
|
+
extensions << ext if File.exists?(ext)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
extensions = [extensions].flatten.compact
|
|
103
|
+
|
|
104
|
+
template =
|
|
105
|
+
if test(?e, 'gemspec.erb')
|
|
106
|
+
Template{ IO.read('gemspec.erb') }
|
|
107
|
+
else
|
|
108
|
+
Template {
|
|
109
|
+
<<-__
|
|
110
|
+
## #{ lib }.gemspec
|
|
111
|
+
#
|
|
112
|
+
|
|
113
|
+
Gem::Specification::new do |spec|
|
|
114
|
+
spec.name = #{ lib.inspect }
|
|
115
|
+
spec.version = #{ version.inspect }
|
|
116
|
+
spec.platform = Gem::Platform::RUBY
|
|
117
|
+
spec.summary = #{ lib.inspect }
|
|
118
|
+
spec.description = #{ description.inspect }
|
|
119
|
+
|
|
120
|
+
spec.files = #{ files.inspect }
|
|
121
|
+
spec.executables = #{ executables.inspect }
|
|
122
|
+
|
|
123
|
+
spec.require_path = "lib"
|
|
124
|
+
|
|
125
|
+
spec.has_rdoc = #{ has_rdoc.inspect }
|
|
126
|
+
spec.test_files = #{ test_files.inspect }
|
|
127
|
+
|
|
128
|
+
# spec.add_dependency 'lib', '>= version'
|
|
129
|
+
spec.add_dependency 'uuidtools'
|
|
130
|
+
|
|
131
|
+
spec.extensions.push(*#{ extensions.inspect })
|
|
132
|
+
|
|
133
|
+
spec.rubyforge_project = #{ This.rubyforge_project.inspect }
|
|
134
|
+
spec.author = #{ This.author.inspect }
|
|
135
|
+
spec.email = #{ This.email.inspect }
|
|
136
|
+
spec.homepage = #{ This.homepage.inspect }
|
|
137
|
+
end
|
|
138
|
+
__
|
|
139
|
+
}
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
Fu.mkdir_p(This.pkgdir)
|
|
143
|
+
This.gemspec = File.join(This.dir, "#{ This.lib }.gemspec") #File.join(This.pkgdir, "gemspec.rb")
|
|
144
|
+
open("#{ This.gemspec }", "w"){|fd| fd.puts(template)}
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
task :gem => [:clean, :gemspec] do
|
|
148
|
+
Fu.mkdir_p(This.pkgdir)
|
|
149
|
+
before = Dir['*.gem']
|
|
150
|
+
cmd = "gem build #{ This.gemspec }"
|
|
151
|
+
`#{ cmd }`
|
|
152
|
+
after = Dir['*.gem']
|
|
153
|
+
gem = ((after - before).first || after.first) or abort('no gem!')
|
|
154
|
+
Fu.mv gem, This.pkgdir
|
|
155
|
+
This.gem = File.basename(gem)
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
task :readme do
|
|
159
|
+
samples = ''
|
|
160
|
+
prompt = '~ > '
|
|
161
|
+
lib = This.lib
|
|
162
|
+
version = This.version
|
|
163
|
+
|
|
164
|
+
Dir['sample*/*'].sort.each do |sample|
|
|
165
|
+
samples << "\n" << " <========< #{ sample } >========>" << "\n\n"
|
|
166
|
+
|
|
167
|
+
cmd = "cat #{ sample }"
|
|
168
|
+
samples << Util.indent(prompt + cmd, 2) << "\n\n"
|
|
169
|
+
samples << Util.indent(`#{ cmd }`, 4) << "\n"
|
|
170
|
+
|
|
171
|
+
cmd = "ruby #{ sample }"
|
|
172
|
+
samples << Util.indent(prompt + cmd, 2) << "\n\n"
|
|
173
|
+
|
|
174
|
+
cmd = "ruby -e'STDOUT.sync=true; exec %(ruby -I ./lib #{ sample })'"
|
|
175
|
+
samples << Util.indent(`#{ cmd } 2>&1`, 4) << "\n"
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
template =
|
|
179
|
+
if test(?e, 'readme.erb')
|
|
180
|
+
Template{ IO.read('readme.erb') }
|
|
181
|
+
else
|
|
182
|
+
Template {
|
|
183
|
+
<<-__
|
|
184
|
+
NAME
|
|
185
|
+
#{ lib }
|
|
186
|
+
|
|
187
|
+
DESCRIPTION
|
|
188
|
+
|
|
189
|
+
INSTALL
|
|
190
|
+
gem install #{ lib }
|
|
191
|
+
|
|
192
|
+
SAMPLES
|
|
193
|
+
#{ samples }
|
|
194
|
+
__
|
|
195
|
+
}
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
open("README", "w"){|fd| fd.puts template}
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
task :clean do
|
|
203
|
+
Dir[File.join(This.pkgdir, '**/**')].each{|entry| Fu.rm_rf(entry)}
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
task :release => [:clean, :gemspec, :gem] do
|
|
208
|
+
gems = Dir[File.join(This.pkgdir, '*.gem')].flatten
|
|
209
|
+
raise "which one? : #{ gems.inspect }" if gems.size > 1
|
|
210
|
+
raise "no gems?" if gems.size < 1
|
|
211
|
+
cmd = "rubyforge login && rubyforge add_release #{ This.rubyforge_project } #{ This.lib } #{ This.version } #{ This.pkgdir }/#{ This.gem }"
|
|
212
|
+
puts cmd
|
|
213
|
+
system cmd
|
|
214
|
+
cmd = "gem push #{ This.pkgdir }/#{ This.gem }"
|
|
215
|
+
puts cmd
|
|
216
|
+
system cmd
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
BEGIN {
|
|
224
|
+
# support for this rakefile
|
|
225
|
+
#
|
|
226
|
+
$VERBOSE = nil
|
|
227
|
+
|
|
228
|
+
require 'ostruct'
|
|
229
|
+
require 'erb'
|
|
230
|
+
require 'fileutils'
|
|
231
|
+
require 'rbconfig'
|
|
232
|
+
|
|
233
|
+
# fu shortcut
|
|
234
|
+
#
|
|
235
|
+
Fu = FileUtils
|
|
236
|
+
|
|
237
|
+
# cache a bunch of stuff about this rakefile/environment
|
|
238
|
+
#
|
|
239
|
+
This = OpenStruct.new
|
|
240
|
+
|
|
241
|
+
This.file = File.expand_path(__FILE__)
|
|
242
|
+
This.dir = File.dirname(This.file)
|
|
243
|
+
This.pkgdir = File.join(This.dir, 'pkg')
|
|
244
|
+
|
|
245
|
+
# grok lib
|
|
246
|
+
#
|
|
247
|
+
lib = ENV['LIB']
|
|
248
|
+
unless lib
|
|
249
|
+
lib = File.basename(Dir.pwd).sub(/[-].*$/, '')
|
|
250
|
+
end
|
|
251
|
+
This.lib = lib
|
|
252
|
+
|
|
253
|
+
# grok version
|
|
254
|
+
#
|
|
255
|
+
version = ENV['VERSION']
|
|
256
|
+
unless version
|
|
257
|
+
require "./lib/#{ This.lib }"
|
|
258
|
+
This.name = lib.capitalize
|
|
259
|
+
This.object = eval(This.name)
|
|
260
|
+
version = This.object.send(:version)
|
|
261
|
+
end
|
|
262
|
+
This.version = version
|
|
263
|
+
|
|
264
|
+
# we need to know the name of the lib an it's version
|
|
265
|
+
#
|
|
266
|
+
abort('no lib') unless This.lib
|
|
267
|
+
abort('no version') unless This.version
|
|
268
|
+
|
|
269
|
+
# discover full path to this ruby executable
|
|
270
|
+
#
|
|
271
|
+
c = Config::CONFIG
|
|
272
|
+
bindir = c["bindir"] || c['BINDIR']
|
|
273
|
+
ruby_install_name = c['ruby_install_name'] || c['RUBY_INSTALL_NAME'] || 'ruby'
|
|
274
|
+
ruby_ext = c['EXEEXT'] || ''
|
|
275
|
+
ruby = File.join(bindir, (ruby_install_name + ruby_ext))
|
|
276
|
+
This.ruby = ruby
|
|
277
|
+
|
|
278
|
+
# some utils
|
|
279
|
+
#
|
|
280
|
+
module Util
|
|
281
|
+
def indent(s, n = 2)
|
|
282
|
+
s = unindent(s)
|
|
283
|
+
ws = ' ' * n
|
|
284
|
+
s.gsub(%r/^/, ws)
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def unindent(s)
|
|
288
|
+
indent = nil
|
|
289
|
+
s.each_line do |line|
|
|
290
|
+
next if line =~ %r/^\s*$/
|
|
291
|
+
indent = line[%r/^\s*/] and break
|
|
292
|
+
end
|
|
293
|
+
indent ? s.gsub(%r/^#{ indent }/, "") : s
|
|
294
|
+
end
|
|
295
|
+
extend self
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
# template support
|
|
299
|
+
#
|
|
300
|
+
class Template
|
|
301
|
+
def initialize(&block)
|
|
302
|
+
@block = block.binding
|
|
303
|
+
@template = block.call.to_s
|
|
304
|
+
end
|
|
305
|
+
def expand(b=nil)
|
|
306
|
+
ERB.new(Util.unindent(@template)).result(b||@block)
|
|
307
|
+
end
|
|
308
|
+
alias_method 'to_s', 'expand'
|
|
309
|
+
end
|
|
310
|
+
def Template(*args, &block) Template.new(*args, &block) end
|
|
311
|
+
|
|
312
|
+
# colored console output support
|
|
313
|
+
#
|
|
314
|
+
This.ansi = {
|
|
315
|
+
:clear => "\e[0m",
|
|
316
|
+
:reset => "\e[0m",
|
|
317
|
+
:erase_line => "\e[K",
|
|
318
|
+
:erase_char => "\e[P",
|
|
319
|
+
:bold => "\e[1m",
|
|
320
|
+
:dark => "\e[2m",
|
|
321
|
+
:underline => "\e[4m",
|
|
322
|
+
:underscore => "\e[4m",
|
|
323
|
+
:blink => "\e[5m",
|
|
324
|
+
:reverse => "\e[7m",
|
|
325
|
+
:concealed => "\e[8m",
|
|
326
|
+
:black => "\e[30m",
|
|
327
|
+
:red => "\e[31m",
|
|
328
|
+
:green => "\e[32m",
|
|
329
|
+
:yellow => "\e[33m",
|
|
330
|
+
:blue => "\e[34m",
|
|
331
|
+
:magenta => "\e[35m",
|
|
332
|
+
:cyan => "\e[36m",
|
|
333
|
+
:white => "\e[37m",
|
|
334
|
+
:on_black => "\e[40m",
|
|
335
|
+
:on_red => "\e[41m",
|
|
336
|
+
:on_green => "\e[42m",
|
|
337
|
+
:on_yellow => "\e[43m",
|
|
338
|
+
:on_blue => "\e[44m",
|
|
339
|
+
:on_magenta => "\e[45m",
|
|
340
|
+
:on_cyan => "\e[46m",
|
|
341
|
+
:on_white => "\e[47m"
|
|
342
|
+
}
|
|
343
|
+
def say(phrase, *args)
|
|
344
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
|
345
|
+
options[:color] = args.shift.to_s.to_sym unless args.empty?
|
|
346
|
+
keys = options.keys
|
|
347
|
+
keys.each{|key| options[key.to_s.to_sym] = options.delete(key)}
|
|
348
|
+
|
|
349
|
+
color = options[:color]
|
|
350
|
+
bold = options.has_key?(:bold)
|
|
351
|
+
|
|
352
|
+
parts = [phrase]
|
|
353
|
+
parts.unshift(This.ansi[color]) if color
|
|
354
|
+
parts.unshift(This.ansi[:bold]) if bold
|
|
355
|
+
parts.push(This.ansi[:clear]) if parts.size > 1
|
|
356
|
+
|
|
357
|
+
method = options[:method] || :puts
|
|
358
|
+
|
|
359
|
+
Kernel.send(method, parts.join)
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
# always run out of the project dir
|
|
363
|
+
#
|
|
364
|
+
Dir.chdir(This.dir)
|
|
365
|
+
}
|
data/lib/upload_cache.rb
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
require 'uuidtools'
|
|
2
|
+
require 'fileutils'
|
|
3
|
+
require 'cgi'
|
|
4
|
+
|
|
5
|
+
class UploadCache
|
|
6
|
+
Version = '1.0.0'
|
|
7
|
+
|
|
8
|
+
README = <<-__
|
|
9
|
+
NAME
|
|
10
|
+
upload_cache.rb
|
|
11
|
+
|
|
12
|
+
DESCRIPTION
|
|
13
|
+
a small utility library to facility caching http file uploads between
|
|
14
|
+
form validation failures. designed for rails, but usable anywhere.
|
|
15
|
+
|
|
16
|
+
USAGE
|
|
17
|
+
in the controller
|
|
18
|
+
|
|
19
|
+
def upload
|
|
20
|
+
@upload_cache = UploadCache.for(params, :upload)
|
|
21
|
+
|
|
22
|
+
@record = Model.new(params)
|
|
23
|
+
|
|
24
|
+
if request.get?
|
|
25
|
+
render and return
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
if request.post?
|
|
29
|
+
@record.save!
|
|
30
|
+
@upload_cache.clear!
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
in the view
|
|
36
|
+
|
|
37
|
+
<input type='file' name='upload />
|
|
38
|
+
|
|
39
|
+
<%= @upload_cache.hidden %>
|
|
40
|
+
|
|
41
|
+
<!-- optionally, you can show any uploaded upload -->
|
|
42
|
+
|
|
43
|
+
<% if url = @upload_cache.url %>
|
|
44
|
+
you already uploaded: <img src='<%= raw url %>' />
|
|
45
|
+
<% end %>
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
in a rake task
|
|
49
|
+
|
|
50
|
+
UploadCache.clear! ### nuke old files once per day
|
|
51
|
+
|
|
52
|
+
__
|
|
53
|
+
|
|
54
|
+
class << UploadCache
|
|
55
|
+
def version
|
|
56
|
+
UploadCache::Version
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def base
|
|
60
|
+
@base ||= 'system/uploads/cache'
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def base=(base)
|
|
64
|
+
@base = base.to_s.sub(%r|^/+|, '')
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def url
|
|
68
|
+
'/' + base
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def root
|
|
72
|
+
@root ||= File.join(Rails.root, 'public', base)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def uuid(*args)
|
|
76
|
+
UUIDTools::UUID.timestamp_create.to_s
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def tmpdir(&block)
|
|
80
|
+
tmpdir = File.join(root, uuid)
|
|
81
|
+
|
|
82
|
+
if block
|
|
83
|
+
FileUtils.mkdir_p(tmpdir)
|
|
84
|
+
block.call(tmpdir)
|
|
85
|
+
else
|
|
86
|
+
tmpdir
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def cleanname(path)
|
|
91
|
+
basename = File.basename(path.to_s)
|
|
92
|
+
CGI.unescape(basename).gsub(%r/[^0-9a-zA-Z_@)(~.-]/, '_').gsub(%r/_+/,'_')
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def cache_key_for(key)
|
|
96
|
+
"#{ key }__cache"
|
|
97
|
+
end
|
|
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
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
return new(key, path=nil)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def finalizer(object_id)
|
|
128
|
+
if fd = IOs[object_id]
|
|
129
|
+
IO.for_fd(fd).close
|
|
130
|
+
IOs.delete(object_id)
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
UUIDPattern = %r/^[a-zA-Z0-9-]+$/io
|
|
135
|
+
Age = 60 * 60 * 24
|
|
136
|
+
|
|
137
|
+
def clear!(options = {})
|
|
138
|
+
glob = File.join(root, '*')
|
|
139
|
+
age = Integer(options[:age] || options['age'] || Age)
|
|
140
|
+
since = options[:since] || options['since'] || Time.now
|
|
141
|
+
|
|
142
|
+
Dir.glob(glob) do |entry|
|
|
143
|
+
begin
|
|
144
|
+
next unless test(?d, entry)
|
|
145
|
+
next unless File.basename(entry) =~ UUIDPattern
|
|
146
|
+
|
|
147
|
+
files = Dir.glob(File.join(entry, '**/**'))
|
|
148
|
+
|
|
149
|
+
all_files_are_old =
|
|
150
|
+
files.all? do |file|
|
|
151
|
+
begin
|
|
152
|
+
stat = File.stat(file)
|
|
153
|
+
age = since - stat.atime
|
|
154
|
+
age >= Age
|
|
155
|
+
rescue
|
|
156
|
+
false
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
FileUtils.rm_rf(entry) if all_files_are_old
|
|
161
|
+
rescue
|
|
162
|
+
next
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
attr_accessor :key
|
|
169
|
+
attr_accessor :cache_key
|
|
170
|
+
attr_accessor :path
|
|
171
|
+
attr_accessor :dirname
|
|
172
|
+
attr_accessor :basename
|
|
173
|
+
attr_accessor :value
|
|
174
|
+
attr_accessor :io
|
|
175
|
+
|
|
176
|
+
IOs = {}
|
|
177
|
+
|
|
178
|
+
def initialize(key, path)
|
|
179
|
+
@key = key.to_s
|
|
180
|
+
@cache_key = UploadCache.cache_key_for(key)
|
|
181
|
+
|
|
182
|
+
if path
|
|
183
|
+
@path = path
|
|
184
|
+
@dirname, @basename = File.split(@path)
|
|
185
|
+
@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
|
+
else
|
|
190
|
+
@path = nil
|
|
191
|
+
@value = nil
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def hidden
|
|
196
|
+
raw("<input type='hidden' name='#{ @cache_key }' value='#{ @value }' />") if @value
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def to_s
|
|
200
|
+
hidden.to_s
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def url
|
|
204
|
+
File.join(UploadCache.url, @value) if @value
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
module HtmlSafe
|
|
208
|
+
def html_safe() self end
|
|
209
|
+
def html_safe?() self end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def raw(*args)
|
|
213
|
+
string = args.join
|
|
214
|
+
unless string.respond_to?(:html_safe)
|
|
215
|
+
string.extend(HtmlSafe)
|
|
216
|
+
end
|
|
217
|
+
string.html_safe
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def clear!
|
|
221
|
+
FileUtils.rm_rf(@dirname) if test(?d, @dirname)
|
|
222
|
+
rescue
|
|
223
|
+
nil
|
|
224
|
+
ensure
|
|
225
|
+
@io.close
|
|
226
|
+
IOs.delete(object_id)
|
|
227
|
+
Thread.new{ UploadCache.clear! }
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
Upload_cache = UploadCache unless defined?(Upload_cache)
|
|
232
|
+
|
|
233
|
+
if defined?(Rails.env)
|
|
234
|
+
unless Rails.env.production?
|
|
235
|
+
if defined?(unloadable)
|
|
236
|
+
unloadable(UploadCache)
|
|
237
|
+
unloadable(Upload_cache)
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: upload_cache
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
hash: 23
|
|
5
|
+
prerelease:
|
|
6
|
+
segments:
|
|
7
|
+
- 1
|
|
8
|
+
- 0
|
|
9
|
+
- 0
|
|
10
|
+
version: 1.0.0
|
|
11
|
+
platform: ruby
|
|
12
|
+
authors:
|
|
13
|
+
- Ara T. Howard
|
|
14
|
+
autorequire:
|
|
15
|
+
bindir: bin
|
|
16
|
+
cert_chain: []
|
|
17
|
+
|
|
18
|
+
date: 2011-03-16 00:00:00 -06:00
|
|
19
|
+
default_executable:
|
|
20
|
+
dependencies:
|
|
21
|
+
- !ruby/object:Gem::Dependency
|
|
22
|
+
name: uuidtools
|
|
23
|
+
prerelease: false
|
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
|
25
|
+
none: false
|
|
26
|
+
requirements:
|
|
27
|
+
- - ">="
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
hash: 3
|
|
30
|
+
segments:
|
|
31
|
+
- 0
|
|
32
|
+
version: "0"
|
|
33
|
+
type: :runtime
|
|
34
|
+
version_requirements: *id001
|
|
35
|
+
description: "description: upload_cache kicks the ass"
|
|
36
|
+
email: ara.t.howard@gmail.com
|
|
37
|
+
executables: []
|
|
38
|
+
|
|
39
|
+
extensions: []
|
|
40
|
+
|
|
41
|
+
extra_rdoc_files: []
|
|
42
|
+
|
|
43
|
+
files:
|
|
44
|
+
- lib/upload_cache.rb
|
|
45
|
+
- Rakefile
|
|
46
|
+
- README
|
|
47
|
+
has_rdoc: true
|
|
48
|
+
homepage: http://github.com/ahoward/upload_cache
|
|
49
|
+
licenses: []
|
|
50
|
+
|
|
51
|
+
post_install_message:
|
|
52
|
+
rdoc_options: []
|
|
53
|
+
|
|
54
|
+
require_paths:
|
|
55
|
+
- lib
|
|
56
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
57
|
+
none: false
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
hash: 3
|
|
62
|
+
segments:
|
|
63
|
+
- 0
|
|
64
|
+
version: "0"
|
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
66
|
+
none: false
|
|
67
|
+
requirements:
|
|
68
|
+
- - ">="
|
|
69
|
+
- !ruby/object:Gem::Version
|
|
70
|
+
hash: 3
|
|
71
|
+
segments:
|
|
72
|
+
- 0
|
|
73
|
+
version: "0"
|
|
74
|
+
requirements: []
|
|
75
|
+
|
|
76
|
+
rubyforge_project: codeforpeople
|
|
77
|
+
rubygems_version: 1.4.2
|
|
78
|
+
signing_key:
|
|
79
|
+
specification_version: 3
|
|
80
|
+
summary: upload_cache
|
|
81
|
+
test_files: []
|
|
82
|
+
|