jnicklas-carrierwave 0.1.1 → 0.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.
@@ -15,39 +15,63 @@ module CarrierWave
15
15
  # these are *very* simple (they are only a dozen lines of code), so adding your own should
16
16
  # be trivial.
17
17
  #
18
- class Uploader
18
+ module Uploader
19
19
 
20
- class << self
20
+ def self.append_features(base) #:nodoc:
21
+ super
22
+ base.extend(ClassMethods)
23
+ end
21
24
 
25
+ ##
26
+ # Generates a unique cache id for use in the caching system
27
+ #
28
+ # === Returns
29
+ #
30
+ # [String] a cache id in the format YYYYMMDD-HHMM-PID-RND
31
+ #
32
+ def self.generate_cache_id
33
+ Time.now.strftime('%Y%m%d-%H%M') + '-' + Process.pid.to_s + '-' + ("%04d" % rand(9999))
34
+ end
35
+
36
+ module ClassMethods
37
+
22
38
  ##
23
- # Returns a list of processor callbacks which have been declared for this uploader
39
+ # Lists processor callbacks declared
24
40
  #
25
- # @return [String]
41
+ # === Returns
42
+ #
43
+ # [Array[Array[Symbol, Array]]] a list of processor callbacks which have been declared for this uploader
26
44
  #
27
45
  def processors
28
46
  @processors ||= []
29
47
  end
30
-
48
+
31
49
  ##
32
50
  # Adds a processor callback which applies operations as a file is uploaded.
33
51
  # The argument may be the name of any method of the uploader, expressed as a symbol,
34
52
  # or a list of such methods, or a hash where the key is a method and the value is
35
53
  # an array of arguments to call the method with
36
54
  #
37
- # @param [*Symbol, Hash{Symbol => Array[]}] args
38
- # @example
39
- # class MyUploader < CarrierWave::Uploader
55
+ # === Parameters
56
+ #
57
+ # args (*Symbol, Hash{Symbol => Array[]})
58
+ #
59
+ # === Examples
60
+ #
61
+ # class MyUploader
62
+ # include CarrierWave::Uploader
63
+ #
40
64
  # process :sepiatone, :vignette
41
65
  # process :scale => [200, 200]
42
- #
66
+ #
43
67
  # def sepiatone
44
68
  # ...
45
69
  # end
46
- #
70
+ #
47
71
  # def vignette
48
72
  # ...
49
73
  # end
50
- #
74
+ #
51
75
  # def scale(height, width)
52
76
  # ...
53
77
  # end
@@ -64,7 +88,7 @@ module CarrierWave
64
88
  end
65
89
  end
66
90
  end
67
-
91
+
68
92
  ##
69
93
  # Sets the storage engine to be used when storing files with this uploader.
70
94
  # Can be any class that implements a #store!(CarrierWave::SanitizedFile) and a #retrieve!
@@ -73,14 +97,21 @@ module CarrierWave
73
97
  # to by a symbol, which should be more convenient
74
98
  #
75
99
  # If no argument is given, it will simply return the currently used storage engine.
76
- #
77
- # @param [Symbol, Class] storage The storage engine to use for this uploader
78
- # @return [Class] the storage engine to be used with this uploader
79
- # @example
100
+ #
101
+ # === Parameters
102
+ #
103
+ # [storage (Symbol, Class)] The storage engine to use for this uploader
104
+ #
105
+ # === Returns
106
+ #
107
+ # [Class] the storage engine to be used with this uploader
108
+ #
109
+ # === Examples
110
+ #
80
111
  # storage :file
81
112
  # storage CarrierWave::Storage::File
82
113
  # storage MyCustomStorageEngine
83
- #
114
+ #
84
115
  def storage(storage = nil)
85
116
  if storage.is_a?(Symbol)
86
117
  @storage = get_storage_by_symbol(storage)
@@ -101,54 +132,54 @@ module CarrierWave
101
132
  end
102
133
 
103
134
  alias_method :storage=, :storage
104
-
105
- attr_accessor :version_name
135
+
136
+ def version_names
137
+ @version_names ||= []
138
+ end
106
139
 
107
140
  ##
108
141
  # Adds a new version to this uploader
109
142
  #
110
- # @param [#to_sym] name name of the version
111
- # @param [Proc] &block a block to eval on this version of the uploader
143
+ # === Parameters
144
+ #
145
+ # [name (#to_sym)] name of the version
146
+ # [&block (Proc)] a block to eval on this version of the uploader
112
147
  #
113
148
  def version(name, &block)
114
149
  name = name.to_sym
115
- klass = Class.new(self)
116
- klass.version_name = name
117
- klass.class_eval(&block) if block
118
- versions[name] = klass
119
- class_eval <<-RUBY
120
- def #{name}
121
- versions[:#{name}]
122
- end
123
- RUBY
150
+ unless versions[name]
151
+ versions[name] = Class.new(self)
152
+ versions[name].version_names.push(*version_names)
153
+ versions[name].version_names.push(name)
154
+ class_eval <<-RUBY
155
+ def #{name}
156
+ versions[:#{name}]
157
+ end
158
+ RUBY
159
+ end
160
+ versions[name].class_eval(&block) if block
161
+ versions[name]
124
162
  end
125
163
 
126
164
  ##
127
- # @return [Hash{Symbol => Class}] a list of versions available for this uploader
165
+ # === Returns
166
+ #
167
+ # [Hash{Symbol => Class}] a list of versions available for this uploader
128
168
  #
129
169
  def versions
130
170
  @versions ||= {}
131
171
  end
132
172
 
133
- ##
134
- # Generates a unique cache id for use in the caching system
135
- #
136
- # @return [String] a cache if in the format YYYYMMDD-HHMM-PID-RND
137
- #
138
- def generate_cache_id
139
- Time.now.strftime('%Y%m%d-%H%M') + '-' + Process.pid.to_s + '-' + ("%04d" % rand(9999))
140
- end
141
-
142
173
  private
143
-
174
+
144
175
  def get_storage_by_symbol(symbol)
145
- CarrierWave.config[:storage_engines][symbol]
176
+ eval(CarrierWave.config[:storage_engines][symbol])
146
177
  end
147
-
148
- end # class << self
149
-
178
+
179
+ end # ClassMethods
180
+
150
181
  attr_reader :file, :model, :mounted_as
151
-
182
+
152
183
  ##
153
184
  # If a model is given as the first parameter, it will stored in the uploader, and
154
185
  # available throught +#model+. Likewise, mounted_as stores the name of the column
@@ -158,10 +189,16 @@ module CarrierWave
158
189
  # If you do not wish to mount your uploaders with the ORM extensions in -more then you
159
190
  # can override this method inside your uploader.
160
191
  #
161
- # @param [Object] model Any kind of model object
162
- # @param [Symbol] mounted_as The name of the column where this uploader is mounted
163
- # @example
164
- # class MyUploader < CarrierWave::Uploader
192
+ # === Parameters
193
+ #
194
+ # [model (Object)] Any kind of model object
195
+ # [mounted_as (Symbol)] The name of the column where this uploader is mounted
196
+ #
197
+ # === Examples
198
+ #
199
+ # class MyUploader
200
+ # include CarrierWave::Uploader
201
+ #
165
202
  # def store_dir
166
203
  # File.join('public', 'files', mounted_as, model.permalink)
167
204
  # end
@@ -171,14 +208,16 @@ module CarrierWave
171
208
  @model = model
172
209
  @mounted_as = mounted_as
173
210
  end
174
-
211
+
175
212
  ##
176
- # @return [Boolean] Whether the uploaded file is blank
213
+ # === Returns
214
+ #
215
+ # [Boolean] Whether the uploaded file is blank
177
216
  #
178
217
  def blank?
179
- !file or file.empty?
218
+ !file or file.blank?
180
219
  end
181
-
220
+
182
221
  ##
183
222
  # Apply all process callbacks added through CarrierWave.process
184
223
  #
@@ -187,18 +226,24 @@ module CarrierWave
187
226
  self.send(method, *args)
188
227
  end
189
228
  end
190
-
229
+
191
230
  ##
192
- # @return [String] the path where the file is currently located.
231
+ # === Returns
232
+ #
233
+ # [String] the path where the file is currently located.
193
234
  #
194
235
  def current_path
195
236
  file.path if file.respond_to?(:path)
196
237
  end
197
-
238
+
239
+ alias_method :path, :current_path
240
+
198
241
  ##
199
242
  # Returns a hash mapping the name of each version of the uploader to an instance of it
200
243
  #
201
- # @return [Hash{Symbol => CarrierWave::Uploader}] a list of uploader instances
244
+ # === Returns
245
+ #
246
+ # [Hash{Symbol => CarrierWave::Uploader}] a list of uploader instances
202
247
  #
203
248
  def versions
204
249
  return @versions if @versions
@@ -210,7 +255,9 @@ module CarrierWave
210
255
  end
211
256
 
212
257
  ##
213
- # @return [String] the location where this file is accessible via a url
258
+ # === Returns
259
+ #
260
+ # [String] the location where this file is accessible via a url
214
261
  #
215
262
  def url
216
263
  if file.respond_to?(:url) and not file.url.blank?
@@ -219,18 +266,31 @@ module CarrierWave
219
266
  File.expand_path(current_path).gsub(File.expand_path(public), '')
220
267
  end
221
268
  end
222
-
269
+
223
270
  alias_method :to_s, :url
224
-
271
+
225
272
  ##
226
273
  # Returns a string that uniquely identifies the last stored file
227
274
  #
228
- # @return [String] uniquely identifies a file
275
+ # === Returns
276
+ #
277
+ # [String] uniquely identifies a file
229
278
  #
230
279
  def identifier
231
280
  file.identifier if file.respond_to?(:identifier)
232
281
  end
233
-
282
+
283
+ ##
284
+ # Read the contents of the file
285
+ #
286
+ # === Returns
287
+ #
288
+ # [String] contents of the file
289
+ #
290
+ def read
291
+ file.read if file.respond_to?(:read)
292
+ end
293
+
234
294
  ##
235
295
  # Override this in your Uploader to change the filename.
236
296
  #
@@ -241,28 +301,36 @@ module CarrierWave
241
301
  # Do not use the version_name in the filename, as it will prevent versions from being
242
302
  # loaded correctly.
243
303
  #
244
- # @return [String] a filename
304
+ # === Returns
305
+ #
306
+ # [String] a filename
245
307
  #
246
308
  def filename
247
309
  @filename
248
310
  end
249
311
 
250
312
  ##
251
- # @return [String] the name of this version of the uploader
313
+ # === Returns
314
+ #
315
+ # [String] the name of this version of the uploader
252
316
  #
253
317
  def version_name
254
- self.class.version_name
318
+ self.class.version_names.join('_').to_sym unless self.class.version_names.blank?
255
319
  end
256
-
320
+
257
321
  ##
258
- # @return [String] the directory that is the root of the application
322
+ # === Returns
323
+ #
324
+ # [String] the directory that is the root of the application
259
325
  #
260
326
  def root
261
327
  CarrierWave.config[:root]
262
328
  end
263
-
329
+
264
330
  ##
265
- # @return [String] the directory where files will be publically accessible
331
+ # === Returns
332
+ #
333
+ # [String] the directory where files will be publically accessible
266
334
  #
267
335
  def public
268
336
  CarrierWave.config[:public]
@@ -272,55 +340,73 @@ module CarrierWave
272
340
  # Override this method in your uploader to provide a white list of extensions which
273
341
  # are allowed to be uploaded.
274
342
  #
275
- # @return [NilClass, Array[String]] a white list of extensions which are allowed to be uploaded
276
- # @example
343
+ # === Returns
344
+ #
345
+ # [NilClass, Array[String]] a white list of extensions which are allowed to be uploaded
346
+ #
347
+ # === Examples
348
+ #
277
349
  # def extension_white_list
278
350
  # %w(jpg jpeg gif png)
279
351
  # end
280
352
  #
281
353
  def extension_white_list; end
282
-
354
+
283
355
  ####################
284
356
  ## Cache
285
357
  ####################
286
-
358
+
287
359
  ##
288
360
  # Override this in your Uploader to change the directory where files are cached.
289
361
  #
290
- # @return [String] a directory
362
+ # === Returns
363
+ #
364
+ # [String] a directory
291
365
  #
292
366
  def cache_dir
293
367
  CarrierWave.config[:cache_dir]
294
368
  end
295
-
369
+
296
370
  ##
297
371
  # Returns a String which uniquely identifies the currently cached file for later retrieval
298
372
  #
299
- # @return [String] a cache name, in the format YYYYMMDD-HHMM-PID-RND/filename.txt
373
+ # === Returns
374
+ #
375
+ # [String] a cache name, in the format YYYYMMDD-HHMM-PID-RND/filename.txt
300
376
  #
301
377
  def cache_name
302
378
  File.join(cache_id, [version_name, original_filename].compact.join('_')) if cache_id and original_filename
303
379
  end
304
-
380
+
305
381
  ##
306
382
  # Caches the given file unless a file has already been cached, stored or retrieved.
307
383
  #
308
- # @param [File, IOString, Tempfile] new_file any kind of file object
309
- # @raise [CarrierWave::FormNotMultipart] if the assigned parameter is a string
384
+ # === Parameters
385
+ #
386
+ # [new_file (File, IOString, Tempfile)] any kind of file object
387
+ #
388
+ # === Raises
389
+ #
390
+ # [CarrierWave::FormNotMultipart] if the assigned parameter is a string
310
391
  #
311
392
  def cache(new_file)
312
393
  cache!(new_file) unless file
313
394
  end
314
-
395
+
315
396
  ##
316
397
  # Caches the given file. Calls process! to trigger any process callbacks.
317
398
  #
318
- # @param [File, IOString, Tempfile] new_file any kind of file object
319
- # @raise [CarrierWave::FormNotMultipart] if the assigned parameter is a string
399
+ # === Parameters
400
+ #
401
+ # [new_file (File, IOString, Tempfile)] any kind of file object
402
+ #
403
+ # === Raises
404
+ #
405
+ # [CarrierWave::FormNotMultipart] if the assigned parameter is a string
320
406
  #
321
407
  def cache!(new_file)
322
408
  new_file = CarrierWave::SanitizedFile.new(new_file)
323
- raise CarrierWave::FormNotMultipart if new_file.string?
409
+ raise CarrierWave::FormNotMultipart if new_file.is_path?
324
410
 
325
411
  unless new_file.empty?
326
412
  if extension_white_list and not extension_white_list.include?(new_file.extension.to_s)
@@ -333,8 +419,8 @@ module CarrierWave
333
419
 
334
420
  @filename = new_file.filename
335
421
  self.original_filename = new_file.filename
336
-
337
- @file = @file.copy_to(cache_path)
422
+
423
+ @file = @file.copy_to(cache_path, CarrierWave.config[:permissions])
338
424
  process!
339
425
 
340
426
  versions.each do |name, v|
@@ -343,23 +429,30 @@ module CarrierWave
343
429
  end
344
430
  end
345
431
  end
346
-
432
+
347
433
  ##
348
434
  # Retrieves the file with the given cache_name from the cache, unless a file has
349
435
  # already been cached, stored or retrieved.
350
436
  #
351
- # @param [String] cache_name uniquely identifies a cache file
437
+ # === Parameters
438
+ #
439
+ # [cache_name (String)] uniquely identifies a cache file
352
440
  #
353
441
  def retrieve_from_cache(cache_name)
354
442
  retrieve_from_cache!(cache_name) unless file
355
443
  rescue CarrierWave::InvalidParameter
356
444
  end
357
-
445
+
358
446
  ##
359
447
  # Retrieves the file with the given cache_name from the cache.
360
448
  #
361
- # @param [String] cache_name uniquely identifies a cache file
362
- # @raise [CarrierWave::InvalidParameter] if the cache_name is incorrectly formatted.
449
+ # === Parameters
450
+ #
451
+ # [cache_name (String)] uniquely identifies a cache file
452
+ #
453
+ # === Raises
454
+ #
455
+ # [CarrierWave::InvalidParameter] if the cache_name is incorrectly formatted.
363
456
  #
364
457
  def retrieve_from_cache!(cache_name)
365
458
  self.cache_id, self.original_filename = cache_name.split('/', 2)
@@ -367,22 +460,40 @@ module CarrierWave
367
460
  @file = CarrierWave::SanitizedFile.new(cache_path)
368
461
  versions.each { |name, v| v.retrieve_from_cache!(cache_name) }
369
462
  end
370
-
463
+
371
464
  ####################
372
465
  ## STORE
373
466
  ####################
374
-
467
+
375
468
  ##
376
469
  # Override this in your Uploader to change the directory where the file backend stores files.
377
470
  #
378
471
  # Other backends may or may not use this method, depending on their specific needs.
379
472
  #
380
- # @return [String] a directory
473
+ # === Returns
474
+ #
475
+ # [String] a directory
381
476
  #
382
477
  def store_dir
383
- [CarrierWave.config[:store_dir], version_name].compact.join(File::Separator)
478
+ CarrierWave.config[:store_dir]
384
479
  end
385
-
480
+
481
+ ##
482
+ # Calculates the path where the file should be stored. If +for_file+ is given, it will be
483
+ # used as the filename, otherwise +CarrierWave::Uploader#filename+ is assumed.
484
+ #
485
+ # === Parameters
486
+ #
487
+ # [for_file (String)] name of the file <optional>
488
+ #
489
+ # === Returns
490
+ #
491
+ # [String] the store path
492
+ #
493
+ def store_path(for_file=filename)
494
+ File.join(store_dir, [version_name, for_file].compact.join('_'))
495
+ end
496
+
386
497
  ##
387
498
  # Stores the file by passing it to this Uploader's storage engine, unless a file has
388
499
  # already been cached, stored or retrieved.
@@ -390,18 +501,22 @@ module CarrierWave
390
501
  # If CarrierWave.config[:use_cache] is true, it will first cache the file
391
502
  # and apply any process callbacks before uploading it.
392
503
  #
393
- # @param [File, IOString, Tempfile] new_file any kind of file object
504
+ # === Parameters
505
+ #
506
+ # [new_file (File, IOString, Tempfile)] any kind of file object
394
507
  #
395
508
  def store(new_file)
396
509
  store!(new_file) unless file
397
510
  end
398
-
511
+
399
512
  ##
400
513
  # Stores the file by passing it to this Uploader's storage engine.
401
514
  #
402
515
  # If new_file is omitted, a previously cached file will be stored.
403
516
  #
404
- # @param [File, IOString, Tempfile] new_file any kind of file object
517
+ # === Parameters
518
+ #
519
+ # [new_file (File, IOString, Tempfile)] any kind of file object
405
520
  #
406
521
  def store!(new_file=nil)
407
522
  cache!(new_file) if new_file
@@ -411,49 +526,53 @@ module CarrierWave
411
526
  versions.each { |name, v| v.store!(new_file) }
412
527
  end
413
528
  end
414
-
529
+
415
530
  ##
416
531
  # Retrieves the file from the storage, unless a file has
417
532
  # already been cached, stored or retrieved.
418
- #
419
- # @param [String] identifier uniquely identifies the file to retrieve
533
+ #
534
+ # === Parameters
535
+ #
536
+ # [identifier (String)] uniquely identifies the file to retrieve
420
537
  #
421
538
  def retrieve_from_store(identifier)
422
539
  retrieve_from_store!(identifier) unless file
423
540
  rescue CarrierWave::InvalidParameter
424
541
  end
425
-
542
+
426
543
  ##
427
544
  # Retrieves the file from the storage.
428
- #
429
- # @param [String] identifier uniquely identifies the file to retrieve
545
+ #
546
+ # === Parameters
547
+ #
548
+ # [identifier (String)] uniquely identifies the file to retrieve
430
549
  #
431
550
  def retrieve_from_store!(identifier)
432
551
  @file = storage.retrieve!(self, identifier)
433
552
  versions.each { |name, v| v.retrieve_from_store!(identifier) }
434
553
  end
435
-
554
+
436
555
  private
437
-
556
+
438
557
  def cache_path
439
558
  File.expand_path(File.join(cache_dir, cache_name), public)
440
559
  end
441
-
560
+
442
561
  def storage
443
562
  self.class.storage
444
563
  end
445
-
564
+
446
565
  attr_reader :cache_id, :original_filename
447
566
 
448
567
  def cache_id=(cache_id)
449
568
  raise CarrierWave::InvalidParameter, "invalid cache id" unless cache_id =~ /\A[\d]{8}\-[\d]{4}\-[\d]+\-[\d]{4}\z/
450
569
  @cache_id = cache_id
451
570
  end
452
-
571
+
453
572
  def original_filename=(filename)
454
573
  raise CarrierWave::InvalidParameter, "invalid filename" unless filename =~ /\A[a-z0-9\.\-\+_]+\z/i
455
574
  @original_filename = filename
456
575
  end
457
-
576
+
458
577
  end # Uploader
459
- end # CarrierWave
578
+ end # CarrierWave