carrierwave 0.9.0 → 2.1.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of carrierwave might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/README.md +362 -116
- data/lib/carrierwave/compatibility/paperclip.rb +29 -21
- data/lib/carrierwave/downloader/base.rb +83 -0
- data/lib/carrierwave/downloader/remote_file.rb +65 -0
- data/lib/carrierwave/error.rb +1 -0
- data/lib/carrierwave/locale/en.yml +7 -4
- data/lib/carrierwave/mount.rb +238 -186
- data/lib/carrierwave/mounter.rb +188 -0
- data/lib/carrierwave/orm/activerecord.rb +60 -24
- data/lib/carrierwave/processing/mini_magick.rb +139 -78
- data/lib/carrierwave/processing/rmagick.rb +68 -23
- data/lib/carrierwave/processing.rb +0 -1
- data/lib/carrierwave/sanitized_file.rb +67 -27
- data/lib/carrierwave/storage/abstract.rb +15 -2
- data/lib/carrierwave/storage/file.rb +69 -2
- data/lib/carrierwave/storage/fog.rb +180 -41
- data/lib/carrierwave/storage.rb +1 -7
- data/lib/carrierwave/test/matchers.rb +77 -12
- data/lib/carrierwave/uploader/cache.rb +74 -38
- data/lib/carrierwave/uploader/callbacks.rb +0 -2
- data/lib/carrierwave/uploader/configuration.rb +72 -6
- data/lib/carrierwave/uploader/content_type_blacklist.rb +48 -0
- data/lib/carrierwave/uploader/content_type_whitelist.rb +48 -0
- data/lib/carrierwave/uploader/default_url.rb +3 -5
- data/lib/carrierwave/uploader/download.rb +5 -69
- data/lib/carrierwave/uploader/extension_blacklist.rb +14 -10
- data/lib/carrierwave/uploader/extension_whitelist.rb +13 -10
- data/lib/carrierwave/uploader/file_size.rb +43 -0
- data/lib/carrierwave/uploader/mountable.rb +13 -8
- data/lib/carrierwave/uploader/processing.rb +15 -17
- data/lib/carrierwave/uploader/proxy.rb +16 -7
- data/lib/carrierwave/uploader/remove.rb +0 -2
- data/lib/carrierwave/uploader/serialization.rb +3 -5
- data/lib/carrierwave/uploader/store.rb +17 -24
- data/lib/carrierwave/uploader/url.rb +3 -5
- data/lib/carrierwave/uploader/versions.rb +117 -86
- data/lib/carrierwave/uploader.rb +6 -2
- data/lib/carrierwave/utilities/uri.rb +5 -6
- data/lib/carrierwave/utilities.rb +1 -3
- data/lib/carrierwave/validations/active_model.rb +3 -7
- data/lib/carrierwave/version.rb +1 -1
- data/lib/carrierwave.rb +36 -3
- data/lib/generators/templates/uploader.rb +4 -8
- data/lib/generators/uploader_generator.rb +1 -1
- metadata +195 -94
- data/lib/carrierwave/locale/cs.yml +0 -11
- data/lib/carrierwave/locale/de.yml +0 -11
- data/lib/carrierwave/locale/nl.yml +0 -11
- data/lib/carrierwave/locale/sk.yml +0 -11
- data/lib/carrierwave/processing/mime_types.rb +0 -73
data/lib/carrierwave/mount.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
module CarrierWave
|
4
2
|
|
5
3
|
##
|
@@ -20,15 +18,11 @@ module CarrierWave
|
|
20
18
|
# [Hash{Symbol => CarrierWave}] what uploaders are mounted on which columns
|
21
19
|
#
|
22
20
|
def uploaders
|
23
|
-
@uploaders ||= {}
|
24
|
-
@uploaders = superclass.uploaders.merge(@uploaders) if superclass.respond_to?(:uploaders)
|
25
|
-
@uploaders
|
21
|
+
@uploaders ||= superclass.respond_to?(:uploaders) ? superclass.uploaders.dup : {}
|
26
22
|
end
|
27
23
|
|
28
24
|
def uploader_options
|
29
|
-
@uploader_options ||= {}
|
30
|
-
@uploader_options = superclass.uploader_options.merge(@uploader_options) if superclass.respond_to?(:uploader_options)
|
31
|
-
@uploader_options
|
25
|
+
@uploader_options ||= superclass.respond_to?(:uploader_options) ? superclass.uploader_options.dup : {}
|
32
26
|
end
|
33
27
|
|
34
28
|
##
|
@@ -66,7 +60,7 @@ module CarrierWave
|
|
66
60
|
# will create an anonymous uploader class.
|
67
61
|
#
|
68
62
|
# Passing a block makes it possible to customize the uploader. This can be
|
69
|
-
# convenient for brevity, but if there is any
|
63
|
+
# convenient for brevity, but if there is any significant logic in the
|
70
64
|
# uploader, you should do the right thing and have it in its own file.
|
71
65
|
#
|
72
66
|
# === Added instance methods
|
@@ -96,7 +90,6 @@ module CarrierWave
|
|
96
90
|
# [image_processing_error] Returns an error object if the last file to be assigned caused a processing error
|
97
91
|
# [image_download_error] Returns an error object if the last file to be remotely assigned caused a download error
|
98
92
|
#
|
99
|
-
# [write_image_identifier] Uses the write_uploader method to set the identifier.
|
100
93
|
# [image_identifier] Reads out the identifier of the file
|
101
94
|
#
|
102
95
|
# === Parameters
|
@@ -139,270 +132,329 @@ module CarrierWave
|
|
139
132
|
# end
|
140
133
|
#
|
141
134
|
def mount_uploader(column, uploader=nil, options={}, &block)
|
142
|
-
|
143
|
-
uploader = Class.new(uploader || CarrierWave::Uploader::Base)
|
144
|
-
const_set("Uploader#{uploader.object_id}".gsub('-', '_'), uploader)
|
145
|
-
uploader.class_eval(&block)
|
146
|
-
uploader.recursively_apply_block_to_versions(&block)
|
147
|
-
else
|
148
|
-
uploader ||= begin
|
149
|
-
u = Class.new(CarrierWave::Uploader::Base)
|
150
|
-
const_set("Uploader#{u.object_id}".gsub('-', '_'), u)
|
151
|
-
u
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
uploaders[column.to_sym] = uploader
|
156
|
-
uploader_options[column.to_sym] = options
|
157
|
-
|
158
|
-
include CarrierWave::Mount::Extension
|
159
|
-
|
160
|
-
# Make sure to write over accessors directly defined on the class.
|
161
|
-
# Simply super to the included module below.
|
162
|
-
class_eval <<-RUBY, __FILE__, __LINE__+1
|
163
|
-
def #{column}; super; end
|
164
|
-
def #{column}=(new_file); super; end
|
165
|
-
RUBY
|
135
|
+
mount_base(column, uploader, options, &block)
|
166
136
|
|
167
|
-
# Mixing this in as a Module instead of class_evaling directly, so we
|
168
|
-
# can maintain the ability to super to any of these methods from within
|
169
|
-
# the class.
|
170
137
|
mod = Module.new
|
171
138
|
include mod
|
172
139
|
mod.class_eval <<-RUBY, __FILE__, __LINE__+1
|
173
140
|
|
174
141
|
def #{column}
|
175
|
-
_mounter(:#{column}).
|
142
|
+
_mounter(:#{column}).uploaders[0] ||= _mounter(:#{column}).blank_uploader
|
176
143
|
end
|
177
144
|
|
178
145
|
def #{column}=(new_file)
|
179
|
-
_mounter(:#{column}).cache(new_file)
|
180
|
-
end
|
181
|
-
|
182
|
-
def #{column}?
|
183
|
-
!_mounter(:#{column}).blank?
|
146
|
+
_mounter(:#{column}).cache([new_file])
|
184
147
|
end
|
185
148
|
|
186
149
|
def #{column}_url(*args)
|
187
|
-
|
150
|
+
#{column}.url(*args)
|
188
151
|
end
|
189
152
|
|
190
153
|
def #{column}_cache
|
191
|
-
_mounter(:#{column}).
|
154
|
+
_mounter(:#{column}).cache_names[0]
|
192
155
|
end
|
193
156
|
|
194
157
|
def #{column}_cache=(cache_name)
|
195
|
-
_mounter(:#{column}).
|
158
|
+
_mounter(:#{column}).cache_names = [cache_name]
|
196
159
|
end
|
197
160
|
|
198
161
|
def remote_#{column}_url
|
199
|
-
_mounter(:#{column}).
|
162
|
+
[_mounter(:#{column}).remote_urls].flatten[0]
|
200
163
|
end
|
201
164
|
|
202
165
|
def remote_#{column}_url=(url)
|
203
|
-
_mounter(:#{column}).
|
204
|
-
end
|
205
|
-
|
206
|
-
def remove_#{column}
|
207
|
-
_mounter(:#{column}).remove
|
166
|
+
_mounter(:#{column}).remote_urls = [url]
|
208
167
|
end
|
209
168
|
|
210
|
-
def
|
211
|
-
_mounter(:#{column}).
|
169
|
+
def remote_#{column}_request_header=(header)
|
170
|
+
_mounter(:#{column}).remote_request_headers = [header]
|
212
171
|
end
|
213
172
|
|
214
|
-
def
|
215
|
-
|
216
|
-
|
173
|
+
def write_#{column}_identifier
|
174
|
+
return if frozen?
|
175
|
+
mounter = _mounter(:#{column})
|
217
176
|
|
218
|
-
|
219
|
-
|
177
|
+
mounter.clear! if mounter.remove?
|
178
|
+
write_uploader(mounter.serialization_column, mounter.identifiers.first)
|
220
179
|
end
|
221
180
|
|
222
|
-
def
|
223
|
-
_mounter(:#{column}).
|
181
|
+
def #{column}_identifier
|
182
|
+
_mounter(:#{column}).read_identifiers[0]
|
224
183
|
end
|
225
184
|
|
226
185
|
def #{column}_integrity_error
|
227
|
-
|
186
|
+
#{column}_integrity_errors.last
|
228
187
|
end
|
229
188
|
|
230
189
|
def #{column}_processing_error
|
231
|
-
|
190
|
+
#{column}_processing_errors.last
|
232
191
|
end
|
233
192
|
|
234
193
|
def #{column}_download_error
|
235
|
-
|
194
|
+
#{column}_download_errors.last
|
236
195
|
end
|
237
196
|
|
238
|
-
def
|
239
|
-
|
197
|
+
def store_previous_changes_for_#{column}
|
198
|
+
attribute_changes = ::ActiveRecord.version.to_s.to_f >= 5.1 ? saved_changes : changes
|
199
|
+
@_previous_changes_for_#{column} = attribute_changes[_mounter(:#{column}).serialization_column]
|
240
200
|
end
|
241
201
|
|
242
|
-
def #{column}
|
243
|
-
|
202
|
+
def remove_previously_stored_#{column}
|
203
|
+
before, after = @_previous_changes_for_#{column}
|
204
|
+
_mounter(:#{column}).remove_previous([before], [after])
|
244
205
|
end
|
206
|
+
RUBY
|
207
|
+
end
|
245
208
|
|
246
|
-
|
247
|
-
|
209
|
+
##
|
210
|
+
# Mounts the given uploader on the given array column. This means that
|
211
|
+
# assigning and reading from the array column will upload and retrieve
|
212
|
+
# multiple files. Supposing that a User class has an uploader mounted on
|
213
|
+
# images, and that images can store an array, for example it could be a
|
214
|
+
# PostgreSQL JSON column. You can assign and retrieve files like this:
|
215
|
+
#
|
216
|
+
# @user.images # => []
|
217
|
+
# @user.images = [some_file_object]
|
218
|
+
# @user.images # => [<Uploader>]
|
219
|
+
#
|
220
|
+
# @user.images[0].url # => '/some_url.png'
|
221
|
+
#
|
222
|
+
# It is also possible (but not recommended) to omit the uploader, which
|
223
|
+
# will create an anonymous uploader class.
|
224
|
+
#
|
225
|
+
# Passing a block makes it possible to customize the uploader. This can be
|
226
|
+
# convenient for brevity, but if there is any significant logic in the
|
227
|
+
# uploader, you should do the right thing and have it in its own file.
|
228
|
+
#
|
229
|
+
# === Added instance methods
|
230
|
+
#
|
231
|
+
# Supposing a class has used +mount_uploaders+ to mount an uploader on a column
|
232
|
+
# named +images+, in that case the following methods will be added to the class:
|
233
|
+
#
|
234
|
+
# [images] Returns an array of uploaders for each uploaded file
|
235
|
+
# [images=] Caches the given files
|
236
|
+
#
|
237
|
+
# [images_urls] Returns the urls to the uploaded files
|
238
|
+
#
|
239
|
+
# [images_cache] Returns a string that identifies the cache location of the files
|
240
|
+
# [images_cache=] Retrieves the files from the cache based on the given cache name
|
241
|
+
#
|
242
|
+
# [remote_image_urls] Returns previously cached remote urls
|
243
|
+
# [remote_image_urls=] Retrieve files from the given remote urls
|
244
|
+
#
|
245
|
+
# [remove_images] An attribute reader that can be used with a checkbox to mark the files for removal
|
246
|
+
# [remove_images=] An attribute writer that can be used with a checkbox to mark the files for removal
|
247
|
+
# [remove_images?] Whether the files should be removed when store_image! is called.
|
248
|
+
#
|
249
|
+
# [store_images!] Stores all files that have been assigned with +images=+
|
250
|
+
# [remove_images!] Removes the uploaded file from the filesystem.
|
251
|
+
#
|
252
|
+
# [image_integrity_errors] Returns error objects of files which failed to pass integrity check
|
253
|
+
# [image_processing_errors] Returns error objects of files which failed to be processed
|
254
|
+
# [image_download_errors] Returns error objects of files which failed to be downloaded
|
255
|
+
#
|
256
|
+
# [image_identifiers] Reads out the identifiers of the files
|
257
|
+
#
|
258
|
+
# === Parameters
|
259
|
+
#
|
260
|
+
# [column (Symbol)] the attribute to mount this uploader on
|
261
|
+
# [uploader (CarrierWave::Uploader)] the uploader class to mount
|
262
|
+
# [options (Hash{Symbol => Object})] a set of options
|
263
|
+
# [&block (Proc)] customize anonymous uploaders
|
264
|
+
#
|
265
|
+
# === Options
|
266
|
+
#
|
267
|
+
# [:mount_on => Symbol] if the name of the column to be serialized to differs you can override it using this option
|
268
|
+
# [:ignore_integrity_errors => Boolean] if set to true, integrity errors will result in caching failing silently
|
269
|
+
# [:ignore_processing_errors => Boolean] if set to true, processing errors will result in caching failing silently
|
270
|
+
#
|
271
|
+
# === Examples
|
272
|
+
#
|
273
|
+
# Mounting uploaders on different columns.
|
274
|
+
#
|
275
|
+
# class Song
|
276
|
+
# mount_uploaders :lyrics, LyricsUploader
|
277
|
+
# mount_uploaders :alternative_lyrics, LyricsUploader
|
278
|
+
# mount_uploaders :files, SongUploader
|
279
|
+
# end
|
280
|
+
#
|
281
|
+
# This will add an anonymous uploader with only the default settings:
|
282
|
+
#
|
283
|
+
# class Data
|
284
|
+
# mount_uploaders :csv_files
|
285
|
+
# end
|
286
|
+
#
|
287
|
+
# this will add an anonymous uploader overriding the store_dir:
|
288
|
+
#
|
289
|
+
# class Product
|
290
|
+
# mount_uploaders :blueprints do
|
291
|
+
# def store_dir
|
292
|
+
# 'blueprints'
|
293
|
+
# end
|
294
|
+
# end
|
295
|
+
# end
|
296
|
+
#
|
297
|
+
def mount_uploaders(column, uploader=nil, options={}, &block)
|
298
|
+
mount_base(column, uploader, options, &block)
|
248
299
|
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
end
|
300
|
+
mod = Module.new
|
301
|
+
include mod
|
302
|
+
mod.class_eval <<-RUBY, __FILE__, __LINE__+1
|
253
303
|
|
254
|
-
def
|
255
|
-
|
304
|
+
def #{column}
|
305
|
+
_mounter(:#{column}).uploaders
|
256
306
|
end
|
257
307
|
|
258
|
-
def
|
259
|
-
|
260
|
-
@previous_model_for_#{column}.#{column}.remove!
|
261
|
-
@previous_model_for_#{column} = nil
|
262
|
-
end
|
308
|
+
def #{column}=(new_files)
|
309
|
+
_mounter(:#{column}).cache(new_files)
|
263
310
|
end
|
264
311
|
|
265
|
-
|
266
|
-
|
312
|
+
def #{column}_urls(*args)
|
313
|
+
_mounter(:#{column}).urls(*args)
|
314
|
+
end
|
267
315
|
|
268
|
-
|
316
|
+
def #{column}_cache
|
317
|
+
names = _mounter(:#{column}).cache_names
|
318
|
+
names.to_json if names.present?
|
319
|
+
end
|
269
320
|
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
def read_uploader(column); end
|
321
|
+
def #{column}_cache=(cache_name)
|
322
|
+
_mounter(:#{column}).cache_names = JSON.parse(cache_name) if cache_name.present?
|
323
|
+
end
|
274
324
|
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
def write_uploader(column, identifier); end
|
325
|
+
def remote_#{column}_urls
|
326
|
+
_mounter(:#{column}).remote_urls
|
327
|
+
end
|
279
328
|
|
280
|
-
|
329
|
+
def remote_#{column}_urls=(urls)
|
330
|
+
_mounter(:#{column}).remote_urls = urls
|
331
|
+
end
|
281
332
|
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
@_mounters ||= {}
|
286
|
-
@_mounters[column] ||= Mounter.new(self, column)
|
287
|
-
end
|
333
|
+
def remote_#{column}_request_headers=(headers)
|
334
|
+
_mounter(:#{column}).remote_request_headers = headers
|
335
|
+
end
|
288
336
|
|
289
|
-
|
337
|
+
def write_#{column}_identifier
|
338
|
+
return if frozen?
|
339
|
+
mounter = _mounter(:#{column})
|
290
340
|
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
attr_reader :column, :record, :remote_url, :integrity_error, :processing_error, :download_error
|
295
|
-
attr_accessor :remove
|
341
|
+
mounter.clear! if mounter.remove?
|
342
|
+
write_uploader(mounter.serialization_column, mounter.identifiers.presence)
|
343
|
+
end
|
296
344
|
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
@options = record.class.uploader_options[column]
|
301
|
-
end
|
345
|
+
def #{column}_identifiers
|
346
|
+
_mounter(:#{column}).read_identifiers
|
347
|
+
end
|
302
348
|
|
303
|
-
|
304
|
-
|
349
|
+
def store_previous_changes_for_#{column}
|
350
|
+
attribute_changes = ::ActiveRecord.version.to_s.to_f >= 5.1 ? saved_changes : changes
|
351
|
+
@_previous_changes_for_#{column} = attribute_changes[_mounter(:#{column}).serialization_column]
|
352
|
+
end
|
305
353
|
|
306
|
-
|
307
|
-
|
308
|
-
elsif not uploader.identifier.blank?
|
309
|
-
record.write_uploader(serialization_column, uploader.identifier)
|
354
|
+
def remove_previously_stored_#{column}
|
355
|
+
_mounter(:#{column}).remove_previous(*@_previous_changes_for_#{column})
|
310
356
|
end
|
311
|
-
|
357
|
+
RUBY
|
358
|
+
end
|
312
359
|
|
313
|
-
|
314
|
-
|
315
|
-
|
360
|
+
private
|
361
|
+
|
362
|
+
def mount_base(column, uploader=nil, options={}, &block)
|
363
|
+
include CarrierWave::Mount::Extension
|
364
|
+
|
365
|
+
uploader = build_uploader(uploader, &block)
|
366
|
+
uploaders[column.to_sym] = uploader
|
367
|
+
uploader_options[column.to_sym] = options
|
368
|
+
|
369
|
+
# Make sure to write over accessors directly defined on the class.
|
370
|
+
# Simply super to the included module below.
|
371
|
+
class_eval <<-RUBY, __FILE__, __LINE__+1
|
372
|
+
def #{column}; super; end
|
373
|
+
def #{column}=(new_file); super; end
|
374
|
+
RUBY
|
375
|
+
|
376
|
+
mod = Module.new
|
377
|
+
include mod
|
378
|
+
mod.class_eval <<-RUBY, __FILE__, __LINE__+1
|
316
379
|
|
317
|
-
|
318
|
-
|
380
|
+
def #{column}?
|
381
|
+
_mounter(:#{column}).present?
|
382
|
+
end
|
319
383
|
|
320
|
-
|
321
|
-
|
384
|
+
def remove_#{column}
|
385
|
+
_mounter(:#{column}).remove
|
322
386
|
end
|
323
|
-
return @uploader
|
324
|
-
end
|
325
387
|
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
@processing_error = nil
|
330
|
-
rescue CarrierWave::IntegrityError => e
|
331
|
-
@integrity_error = e
|
332
|
-
raise e unless option(:ignore_integrity_errors)
|
333
|
-
rescue CarrierWave::ProcessingError => e
|
334
|
-
@processing_error = e
|
335
|
-
raise e unless option(:ignore_processing_errors)
|
336
|
-
end
|
388
|
+
def remove_#{column}!
|
389
|
+
_mounter(:#{column}).remove!
|
390
|
+
end
|
337
391
|
|
338
|
-
|
339
|
-
|
340
|
-
|
392
|
+
def remove_#{column}=(value)
|
393
|
+
_mounter(:#{column}).remove = value
|
394
|
+
end
|
341
395
|
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
end
|
396
|
+
def remove_#{column}?
|
397
|
+
_mounter(:#{column}).remove?
|
398
|
+
end
|
346
399
|
|
347
|
-
|
348
|
-
|
349
|
-
|
400
|
+
def store_#{column}!
|
401
|
+
_mounter(:#{column}).store!
|
402
|
+
end
|
350
403
|
|
351
|
-
|
404
|
+
def #{column}_integrity_errors
|
405
|
+
_mounter(:#{column}).integrity_errors
|
406
|
+
end
|
352
407
|
|
353
|
-
|
408
|
+
def #{column}_processing_errors
|
409
|
+
_mounter(:#{column}).processing_errors
|
410
|
+
end
|
354
411
|
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
rescue CarrierWave::ProcessingError => e
|
359
|
-
@processing_error = e
|
360
|
-
raise e unless option(:ignore_processing_errors)
|
361
|
-
rescue CarrierWave::IntegrityError => e
|
362
|
-
@integrity_error = e
|
363
|
-
raise e unless option(:ignore_integrity_errors)
|
364
|
-
end
|
412
|
+
def #{column}_download_errors
|
413
|
+
_mounter(:#{column}).download_errors
|
414
|
+
end
|
365
415
|
|
366
|
-
|
367
|
-
|
368
|
-
if remove?
|
369
|
-
uploader.remove!
|
370
|
-
else
|
371
|
-
uploader.store!
|
372
|
-
end
|
416
|
+
def mark_remove_#{column}_false
|
417
|
+
_mounter(:#{column}).remove = false
|
373
418
|
end
|
374
|
-
|
419
|
+
RUBY
|
420
|
+
end
|
375
421
|
|
376
|
-
|
377
|
-
|
378
|
-
end
|
422
|
+
def build_uploader(uploader, &block)
|
423
|
+
return uploader if uploader && !block_given?
|
379
424
|
|
380
|
-
|
381
|
-
|
382
|
-
end
|
425
|
+
uploader = Class.new(uploader || CarrierWave::Uploader::Base)
|
426
|
+
const_set("Uploader#{uploader.object_id}".tr('-', '_'), uploader)
|
383
427
|
|
384
|
-
|
385
|
-
|
428
|
+
if block_given?
|
429
|
+
uploader.class_eval(&block)
|
430
|
+
uploader.recursively_apply_block_to_versions(&block)
|
386
431
|
end
|
387
432
|
|
388
|
-
|
389
|
-
|
390
|
-
end
|
433
|
+
uploader
|
434
|
+
end
|
391
435
|
|
392
|
-
|
393
|
-
|
394
|
-
|
436
|
+
module Extension
|
437
|
+
|
438
|
+
##
|
439
|
+
# overwrite this to read from a serialized attribute
|
440
|
+
#
|
441
|
+
def read_uploader(column); end
|
395
442
|
|
396
|
-
|
443
|
+
##
|
444
|
+
# overwrite this to write to a serialized attribute
|
445
|
+
#
|
446
|
+
def write_uploader(column, identifier); end
|
397
447
|
|
398
448
|
private
|
399
449
|
|
400
|
-
def
|
401
|
-
|
402
|
-
|
450
|
+
def _mounter(column)
|
451
|
+
# We cannot memoize in frozen objects :(
|
452
|
+
return Mounter.new(self, column) if frozen?
|
453
|
+
@_mounters ||= {}
|
454
|
+
@_mounters[column] ||= Mounter.new(self, column)
|
403
455
|
end
|
404
456
|
|
405
|
-
end #
|
457
|
+
end # Extension
|
406
458
|
|
407
459
|
end # Mount
|
408
460
|
end # CarrierWave
|