jnicklas-carrierwave 0.1

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.
@@ -0,0 +1,420 @@
1
+ module CarrierWave
2
+ class Uploader
3
+
4
+ class << self
5
+
6
+ ##
7
+ # Returns a list of processor callbacks which have been declared for this uploader
8
+ #
9
+ # @return [String]
10
+ #
11
+ def processors
12
+ @processors ||= []
13
+ end
14
+
15
+ ##
16
+ # Adds a processor callback which applies operations as a file is uploaded.
17
+ # The argument may be the name of any method of the uploader, expressed as a symbol,
18
+ # or a list of such methods, or a hash where the key is a method and the value is
19
+ # an array of arguments to call the method with
20
+ #
21
+ # @param [*Symbol, Hash{Symbol => Array[]}] args
22
+ # @example
23
+ # class MyUploader < CarrierWave::Uploader
24
+ # process :sepiatone, :vignette
25
+ # process :scale => [200, 200]
26
+ #
27
+ # def sepiatone
28
+ # ...
29
+ # end
30
+ #
31
+ # def vignette
32
+ # ...
33
+ # end
34
+ #
35
+ # def scale(height, width)
36
+ # ...
37
+ # end
38
+ # end
39
+ #
40
+ def process(*args)
41
+ args.each do |arg|
42
+ if arg.is_a?(Hash)
43
+ arg.each do |method, args|
44
+ processors.push([method, args])
45
+ end
46
+ else
47
+ processors.push([arg, []])
48
+ end
49
+ end
50
+ end
51
+
52
+ ##
53
+ # Sets the storage engine to be used when storing files with this uploader.
54
+ # Can be any class that implements a #store!(CarrierWave::SanitizedFile) and a #retrieve!
55
+ # method. See lib/carrierwave/storage/file.rb for an example. Storage engines should
56
+ # be added to CarrierWave.config[:storage_engines] so they can be referred
57
+ # to by a symbol, which should be more convenient
58
+ #
59
+ # If no argument is given, it will simply return the currently used storage engine.
60
+ #
61
+ # @param [Symbol, Class] storage The storage engine to use for this uploader
62
+ # @return [Class] the storage engine to be used with this uploader
63
+ # @example
64
+ # storage :file
65
+ # storage CarrierWave::Storage::File
66
+ # storage MyCustomStorageEngine
67
+ #
68
+ def storage(storage = nil)
69
+ if storage.is_a?(Symbol)
70
+ @storage = get_storage_by_symbol(storage)
71
+ @storage.setup!
72
+ elsif storage
73
+ @storage = storage
74
+ @storage.setup!
75
+ elsif @storage.nil?
76
+ # Get the storage from the superclass if there is one
77
+ @storage = superclass.storage rescue nil
78
+ end
79
+ if @storage.nil?
80
+ # If we were not able to find a store any other way, setup the default store
81
+ @storage ||= get_storage_by_symbol(CarrierWave.config[:storage])
82
+ @storage.setup!
83
+ end
84
+ return @storage
85
+ end
86
+
87
+ alias_method :storage=, :storage
88
+
89
+ attr_accessor :version_name
90
+
91
+ ##
92
+ # Adds a new version to this uploader
93
+ #
94
+ # @param [#to_sym] name name of the version
95
+ # @param [Proc] &block a block to eval on this version of the uploader
96
+ #
97
+ def version(name, &block)
98
+ name = name.to_sym
99
+ klass = Class.new(self)
100
+ klass.version_name = name
101
+ klass.class_eval(&block) if block
102
+ versions[name] = klass
103
+ class_eval <<-RUBY
104
+ def #{name}
105
+ versions[:#{name}]
106
+ end
107
+ RUBY
108
+ end
109
+
110
+ ##
111
+ # @return [Hash{Symbol => Class}] a list of versions available for this uploader
112
+ #
113
+ def versions
114
+ @versions ||= {}
115
+ end
116
+
117
+ ##
118
+ # Generates a unique cache id for use in the caching system
119
+ #
120
+ # @return [String] a cache if in the format YYYYMMDD-HHMM-PID-RND
121
+ #
122
+ def generate_cache_id
123
+ Time.now.strftime('%Y%m%d-%H%M') + '-' + Process.pid.to_s + '-' + ("%04d" % rand(9999))
124
+ end
125
+
126
+ private
127
+
128
+ def get_storage_by_symbol(symbol)
129
+ CarrierWave.config[:storage_engines][symbol]
130
+ end
131
+
132
+ end # class << self
133
+
134
+ attr_reader :file, :model, :mounted_as
135
+
136
+ ##
137
+ # If a model is given as the first parameter, it will stored in the uploader, and
138
+ # available throught +#model+. Likewise, mounted_as stores the name of the column
139
+ # where this instance of the uploader is mounted. These values can then be used inside
140
+ # your uploader.
141
+ #
142
+ # If you do not wish to mount your uploaders with the ORM extensions in -more then you
143
+ # can override this method inside your uploader.
144
+ #
145
+ # @param [Object] model Any kind of model object
146
+ # @param [Symbol] mounted_as The name of the column where this uploader is mounted
147
+ # @example
148
+ # class MyUploader < CarrierWave::Uploader
149
+ # def store_dir
150
+ # File.join('public', 'files', mounted_as, model.permalink)
151
+ # end
152
+ # end
153
+ #
154
+ def initialize(model=nil, mounted_as=nil)
155
+ @model = model
156
+ @mounted_as = mounted_as
157
+ end
158
+
159
+ ##
160
+ # Apply all process callbacks added through CarrierWaveer.process
161
+ #
162
+ def process!
163
+ self.class.processors.each do |method, args|
164
+ self.send(method, *args)
165
+ end
166
+ end
167
+
168
+ ##
169
+ # @return [String] the path where the file is currently located.
170
+ #
171
+ def current_path
172
+ file.path if file.respond_to?(:path)
173
+ end
174
+
175
+ ##
176
+ # Returns a hash mapping the name of each version of the uploader to an instance of it
177
+ #
178
+ # @return [Hash{Symbol => CarrierWave::Uploader}] a list of uploader instances
179
+ #
180
+ def versions
181
+ return @versions if @versions
182
+ @versions = {}
183
+ self.class.versions.each do |name, klass|
184
+ @versions[name] = klass.new(model, mounted_as)
185
+ end
186
+ @versions
187
+ end
188
+
189
+ ##
190
+ # @return [String] the location where this file is accessible via a url
191
+ #
192
+ def url
193
+ if file.respond_to?(:url) and not file.url.blank?
194
+ file.url
195
+ elsif current_path
196
+ File.expand_path(current_path).gsub(File.expand_path(CarrierWave.config[:public]), '')
197
+ end
198
+ end
199
+
200
+ alias_method :to_s, :url
201
+
202
+ ##
203
+ # Returns a string that uniquely identifies the last stored file
204
+ #
205
+ # @return [String] uniquely identifies a file
206
+ #
207
+ def identifier
208
+ file.identifier if file.respond_to?(:identifier)
209
+ end
210
+
211
+ ##
212
+ # Override this in your Uploader to change the filename.
213
+ #
214
+ # Be careful using record ids as filenames. If the filename is stored in the database
215
+ # the record id will be nil when the filename is set. Don't use record ids unless you
216
+ # understand this limitation.
217
+ #
218
+ # Do not use the version_name in the filename, as it will prevent versions from being
219
+ # loaded correctly.
220
+ #
221
+ # @return [String] a filename
222
+ #
223
+ def filename
224
+ @filename
225
+ end
226
+
227
+ ##
228
+ # @return [String] the name of this version of the uploader
229
+ #
230
+ def version_name
231
+ self.class.version_name
232
+ end
233
+
234
+ ##
235
+ # @return [String] the directory relative to which we will upload
236
+ #
237
+ def root
238
+ CarrierWave.config[:root]
239
+ end
240
+
241
+ ####################
242
+ ## Cache
243
+ ####################
244
+
245
+ ##
246
+ # Override this in your Uploader to change the directory where files are cached.
247
+ #
248
+ # @return [String] a directory
249
+ #
250
+ def cache_dir
251
+ CarrierWave.config[:cache_dir]
252
+ end
253
+
254
+ ##
255
+ # Returns a String which uniquely identifies the currently cached file for later retrieval
256
+ #
257
+ # @return [String] a cache name, in the format YYYYMMDD-HHMM-PID-RND/filename.txt
258
+ #
259
+ def cache_name
260
+ File.join(cache_id, [version_name, original_filename].compact.join('_')) if cache_id and original_filename
261
+ end
262
+
263
+ ##
264
+ # Caches the given file unless a file has already been cached, stored or retrieved.
265
+ #
266
+ # @param [File, IOString, Tempfile] new_file any kind of file object
267
+ # @raise [CarrierWave::FormNotMultipart] if the assigned parameter is a string
268
+ #
269
+ def cache(new_file)
270
+ cache!(new_file) unless file
271
+ end
272
+
273
+ ##
274
+ # Caches the given file. Calls process! to trigger any process callbacks.
275
+ #
276
+ # @param [File, IOString, Tempfile] new_file any kind of file object
277
+ # @raise [CarrierWave::FormNotMultipart] if the assigned parameter is a string
278
+ #
279
+ def cache!(new_file)
280
+ self.cache_id = CarrierWave::Uploader.generate_cache_id unless cache_id
281
+ new_file = CarrierWave::SanitizedFile.new(new_file)
282
+ raise CarrierWave::FormNotMultipart, "check that your upload form is multipart encoded" if new_file.string?
283
+
284
+ @file = new_file
285
+
286
+ @filename = new_file.filename
287
+ self.original_filename = new_file.filename
288
+
289
+ @file = @file.copy_to(cache_path)
290
+ process!
291
+
292
+ versions.each do |name, v|
293
+ v.send(:cache_id=, cache_id)
294
+ v.cache!(new_file)
295
+ end
296
+ end
297
+
298
+ ##
299
+ # Retrieves the file with the given cache_name from the cache, unless a file has
300
+ # already been cached, stored or retrieved.
301
+ #
302
+ # @param [String] cache_name uniquely identifies a cache file
303
+ #
304
+ def retrieve_from_cache(cache_name)
305
+ retrieve_from_cache!(cache_name) unless file
306
+ rescue CarrierWave::InvalidParameter
307
+ end
308
+
309
+ ##
310
+ # Retrieves the file with the given cache_name from the cache.
311
+ #
312
+ # @param [String] cache_name uniquely identifies a cache file
313
+ # @raise [CarrierWave::InvalidParameter] if the cache_name is incorrectly formatted.
314
+ #
315
+ def retrieve_from_cache!(cache_name)
316
+ self.cache_id, self.original_filename = cache_name.split('/', 2)
317
+ @filename = original_filename
318
+ @file = CarrierWave::SanitizedFile.new(cache_path)
319
+ versions.each { |name, v| v.retrieve_from_cache!(cache_name) }
320
+ end
321
+
322
+ ####################
323
+ ## STORE
324
+ ####################
325
+
326
+ ##
327
+ # Override this in your Uploader to change the directory where the file backend stores files.
328
+ #
329
+ # Other backends may or may not use this method, depending on their specific needs.
330
+ #
331
+ # @return [String] a directory
332
+ #
333
+ def store_dir
334
+ [CarrierWave.config[:store_dir], version_name].compact.join(File::Separator)
335
+ end
336
+
337
+ ##
338
+ # Stores the file by passing it to this Uploader's storage engine, unless a file has
339
+ # already been cached, stored or retrieved.
340
+ #
341
+ # If CarrierWave.config[:use_cache] is true, it will first cache the file
342
+ # and apply any process callbacks before uploading it.
343
+ #
344
+ # @param [File, IOString, Tempfile] new_file any kind of file object
345
+ #
346
+ def store(new_file)
347
+ store!(new_file) unless file
348
+ end
349
+
350
+ ##
351
+ # Stores the file by passing it to this Uploader's storage engine.
352
+ #
353
+ # If new_file is omitted, a previously cached file will be stored.
354
+ #
355
+ # If CarrierWave.config[:use_cache] is true, it will first cache the file
356
+ # and apply any process callbacks before uploading it.
357
+ #
358
+ # @param [File, IOString, Tempfile] new_file any kind of file object
359
+ #
360
+ def store!(new_file=nil)
361
+ if CarrierWave.config[:use_cache]
362
+ cache!(new_file) if new_file
363
+ @file = storage.store!(self, @file)
364
+ @cache_id = nil
365
+ else
366
+ new_file = CarrierWave::SanitizedFile.new(new_file)
367
+
368
+ @filename = new_file.filename
369
+ self.original_filename = filename
370
+
371
+ @file = storage.store!(self, new_file)
372
+ end
373
+ versions.each { |name, v| v.store!(new_file) }
374
+ end
375
+
376
+ ##
377
+ # Retrieves the file from the storage, unless a file has
378
+ # already been cached, stored or retrieved.
379
+ #
380
+ # @param [String] filename uniquely identifies the file to retrieve
381
+ #
382
+ def retrieve_from_store(filename)
383
+ retrieve_from_store!(filename) unless file
384
+ rescue CarrierWave::InvalidParameter
385
+ end
386
+
387
+ ##
388
+ # Retrieves the file from the storage.
389
+ #
390
+ # @param [String] identifier uniquely identifies the file to retrieve
391
+ #
392
+ def retrieve_from_store!(identifier)
393
+ @file = storage.retrieve!(self, identifier)
394
+ versions.each { |name, v| v.retrieve_from_store!(identifier) }
395
+ end
396
+
397
+ private
398
+
399
+ def cache_path
400
+ File.expand_path(File.join(cache_dir, cache_name), root)
401
+ end
402
+
403
+ def storage
404
+ self.class.storage
405
+ end
406
+
407
+ attr_reader :cache_id, :original_filename
408
+
409
+ def cache_id=(cache_id)
410
+ raise CarrierWave::InvalidParameter, "invalid cache id" unless cache_id =~ /^[\d]{8}\-[\d]{4}\-[\d]+\-[\d]{4}$/
411
+ @cache_id = cache_id
412
+ end
413
+
414
+ def original_filename=(filename)
415
+ raise CarrierWave::InvalidParameter, "invalid filename" unless filename =~ /^[a-z0-9\.\-\+_]+$/i
416
+ @original_filename = filename
417
+ end
418
+
419
+ end # Uploader
420
+ end # CarrierWave
@@ -0,0 +1,63 @@
1
+ require 'fileutils'
2
+
3
+ module CarrierWave
4
+ class << self
5
+ attr_accessor :config
6
+ end
7
+
8
+ class UploadError < StandardError; end
9
+ class NoFileError < UploadError; end
10
+ class FormNotMultipart < UploadError; end
11
+ class InvalidParameter < UploadError; end
12
+ # Should be used by methods used as process callbacks.
13
+ class ProcessingError < UploadError; end
14
+ end
15
+
16
+ dir = File.join(File.dirname(__FILE__), 'carrierwave')
17
+
18
+ require File.join(dir, 'sanitized_file')
19
+ require File.join(dir, 'uploader')
20
+ require File.join(dir, 'mount')
21
+ require File.join(dir, 'storage', 'abstract')
22
+ require File.join(dir, 'storage', 'file')
23
+ require File.join(dir, 'storage', 's3')
24
+
25
+ CarrierWave.config = {
26
+ :storage => :file,
27
+ :use_cache => true,
28
+ :storage_engines => {
29
+ :file => CarrierWave::Storage::File,
30
+ :s3 => CarrierWave::Storage::S3
31
+ },
32
+ :s3 => {
33
+ :access => :public_read
34
+ },
35
+ :store_dir => 'public/uploads',
36
+ :cache_dir => 'public/uploads/tmp'
37
+ }
38
+
39
+ if defined?(Merb)
40
+ CarrierWave.config[:root] = Merb.root
41
+ CarrierWave.config[:public] = Merb.dir_for(:public)
42
+
43
+ orm_path = File.dirname(__FILE__) / 'carrierwave' / 'orm' / Merb.orm
44
+ require orm_path if File.exist?(orm_path + '.rb')
45
+
46
+ Merb.push_path(:model, Merb.root / "app" / "uploaders")
47
+
48
+ Merb.add_generators File.dirname(__FILE__) / 'generators' / 'uploader_generator'
49
+ end
50
+
51
+ if defined?(Rails)
52
+ CarrierWave.config[:root] = Rails.root
53
+ CarrierWave.config[:public] = File.join(Rails.root, 'public')
54
+
55
+ require File.join(File.dirname(__FILE__), "carrierwave", "orm", 'activerecord')
56
+
57
+ ActiveSupport::Dependencies.load_paths << File.join(Rails.root, "app", "uploaders")
58
+ end
59
+
60
+ if defined?(Sinatra)
61
+ CarrierWave.config[:root] = Sinatra::Application.root
62
+ CarrierWave.config[:public] = Sinatra::Application.public
63
+ end
@@ -0,0 +1,32 @@
1
+ class <%= class_name %>Uploader < CarrierWave::Uploader
2
+
3
+ # Include RMagick or ImageScience support
4
+ # include CarrierWave::RMagick
5
+ # include CarrierWave::ImageScience
6
+
7
+ # Choose what kind of storage to use for this uploader
8
+ storage :file
9
+
10
+ # Process files as they are uploaded.
11
+ # process :scale => [200, 300]
12
+ #
13
+ # def scale(width, height)
14
+ # # do something
15
+ # end
16
+
17
+ # Create different verions of your uploaded files
18
+ # version :thumb do
19
+ # process :scale => [50, 50]
20
+ # end
21
+
22
+ # Override the filename of the uploaded files
23
+ # def filename
24
+ # "something"
25
+ # end
26
+
27
+ # Override the directory where uploaded files will be stored
28
+ # def store_dir
29
+ # "something"
30
+ # end
31
+
32
+ end
@@ -0,0 +1,20 @@
1
+ module Merb
2
+ module Generators
3
+ class UploaderGenerator < NamedGenerator
4
+
5
+ def self.source_root
6
+ File.join(File.dirname(__FILE__), 'templates')
7
+ end
8
+
9
+ first_argument :name, :required => true, :desc => "The name of this uploader"
10
+
11
+ template :uploader do |t|
12
+ t.source = 'uploader.rbt'
13
+ t.destination = "app/uploaders/#{file_name}_uploader.rb"
14
+ end
15
+ end
16
+
17
+ add :uploader, UploaderGenerator
18
+
19
+ end
20
+ end
@@ -0,0 +1 @@
1
+ bork bork bork
@@ -0,0 +1 @@
1
+ this is stuff
@@ -0,0 +1 @@
1
+ this is stuff