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.
Files changed (3) hide show
  1. data/lib/upload_cache.rb +152 -60
  2. data/upload_cache.gemspec +28 -0
  3. 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.0.0'
8
+ Version = '1.2.0'
7
9
 
8
- README = <<-__
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 base
60
- @base ||= 'system/uploads/cache'
64
+ def url
65
+ @url ||= "file:/#{ root }"
61
66
  end
62
67
 
63
- def base=(base)
64
- @base = base.to_s.sub(%r|^/+|, '')
68
+ def url=(url)
69
+ @url = '/' + Array(url).join('/').squeeze('/').sub(%r|^/+|, '').sub(%r|/+$|, '')
65
70
  end
66
71
 
67
- def url
68
- '/' + base
72
+ def root
73
+ @root ||= Dir.tmpdir
69
74
  end
70
75
 
71
- def root
72
- @root ||= File.join(Rails.root, 'public', base)
76
+ def root=(root)
77
+ @root = File.expand_path(root)
73
78
  end
74
79
 
75
- def uuid(*args)
76
- UUIDTools::UUID.timestamp_create.to_s
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
- "#{ 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
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, path)
179
- @key = key.to_s
180
- @cache_key = UploadCache.cache_key_for(key)
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='#{ @cache_key }' value='#{ @value }' />") if @value
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
- 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! }
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
- hash: 23
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
- date: 2011-03-16 00:00:00 -06:00
19
- default_executable:
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
- prerelease: false
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
- hash: 3
30
- segments:
31
- - 0
32
- version: "0"
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
33
22
  type: :runtime
34
- version_requirements: *id001
35
- description: "description: upload_cache kicks the ass"
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
- has_rdoc: true
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
- hash: 3
62
- segments:
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
- hash: 3
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.4.2
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
-