carrierwave 1.3.1 → 2.0.0.rc
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 +4 -4
- data/README.md +45 -12
- data/lib/carrierwave.rb +4 -0
- data/lib/carrierwave/downloader/base.rb +50 -0
- data/lib/carrierwave/downloader/remote_file.rb +42 -0
- data/lib/carrierwave/mount.rb +25 -19
- data/lib/carrierwave/mounter.rb +69 -47
- data/lib/carrierwave/orm/activerecord.rb +14 -8
- data/lib/carrierwave/processing/mini_magick.rb +100 -117
- data/lib/carrierwave/processing/rmagick.rb +1 -1
- data/lib/carrierwave/sanitized_file.rb +34 -20
- data/lib/carrierwave/storage.rb +1 -0
- data/lib/carrierwave/storage/file.rb +2 -2
- data/lib/carrierwave/storage/fog.rb +21 -10
- data/lib/carrierwave/uploader.rb +0 -9
- data/lib/carrierwave/uploader/cache.rb +23 -15
- data/lib/carrierwave/uploader/configuration.rb +28 -15
- data/lib/carrierwave/uploader/download.rb +2 -80
- data/lib/carrierwave/uploader/mountable.rb +6 -0
- data/lib/carrierwave/uploader/proxy.rb +2 -2
- data/lib/carrierwave/uploader/serialization.rb +1 -1
- data/lib/carrierwave/uploader/store.rb +5 -3
- data/lib/carrierwave/uploader/url.rb +2 -2
- data/lib/carrierwave/uploader/versions.rb +42 -12
- data/lib/carrierwave/validations/active_model.rb +3 -3
- data/lib/carrierwave/version.rb +1 -1
- metadata +64 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8d930fb9703b4bdb5ec81e14a01a5f07a260f39b52caed16978f193ddfd73159
|
4
|
+
data.tar.gz: 83facb0af8dd50905b36510986a0215d3e6a03b765e83b6b063a6bc8ad7bbaf0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aa813176c7dca0e42e9e131d405eeec2324741c7dff79fc4ceed9c5d16dabb52d967f6e40a025fe431412d91e1cfcb9fd043655271de7d615938f89f9f075179
|
7
|
+
data.tar.gz: 16877c3b9ce32913719f0329b300bae18991de3d642702eed202639a2f9ecb0613e41c766f0ae9adf97d2d64247f86cb3cbdb47f75112542ba01dd82b3653539
|
data/README.md
CHANGED
@@ -30,13 +30,13 @@ $ gem install carrierwave
|
|
30
30
|
In Rails, add it to your Gemfile:
|
31
31
|
|
32
32
|
```ruby
|
33
|
-
gem 'carrierwave', '
|
33
|
+
gem 'carrierwave', '>= 2.0.0.rc', '< 3.0'
|
34
34
|
```
|
35
35
|
|
36
36
|
Finally, restart the server to apply the changes.
|
37
37
|
|
38
|
-
As of version
|
39
|
-
or higher. If you're on Rails
|
38
|
+
As of version 2.0, CarrierWave requires Rails 5.0 or higher and Ruby 2.2
|
39
|
+
or higher. If you're on Rails 4, you should use 1.x.
|
40
40
|
|
41
41
|
## Getting Started
|
42
42
|
|
@@ -163,6 +163,9 @@ class User < ActiveRecord::Base
|
|
163
163
|
end
|
164
164
|
```
|
165
165
|
|
166
|
+
Make sure that you mount the uploader with write (mount_uploaders) with `s` not (mount_uploader)
|
167
|
+
in order to avoid errors when uploading multiple files
|
168
|
+
|
166
169
|
Make sure your file input fields are set up as multiple file fields. For
|
167
170
|
example in Rails you'll want to do something like this:
|
168
171
|
|
@@ -187,6 +190,17 @@ u.avatars[0].current_path # => 'path/to/file.png'
|
|
187
190
|
u.avatars[0].identifier # => 'file.png'
|
188
191
|
```
|
189
192
|
|
193
|
+
If you want to preserve existing files on uploading new one, you can go like:
|
194
|
+
|
195
|
+
```erb
|
196
|
+
<% user.avatars.each do |avatar| %>
|
197
|
+
<%= hidden_field :user, :avatars, multiple: true, value: avatar.identifier %>
|
198
|
+
<% end %>
|
199
|
+
<%= form.file_field :avatars, multiple: true %>
|
200
|
+
```
|
201
|
+
|
202
|
+
Sorting avatars is supported as well by reordering `hidden_field`, an example using jQuery UI Sortable is available [here](https://github.com/carrierwaveuploader/carrierwave/wiki/How-to%3A-Add%2C-remove-and-reorder-images-using-multiple-file-upload).
|
203
|
+
|
190
204
|
## Changing the storage directory
|
191
205
|
|
192
206
|
In order to change where uploaded files are put, just override the `store_dir`
|
@@ -252,6 +266,22 @@ class NoJsonUploader < CarrierWave::Uploader::Base
|
|
252
266
|
end
|
253
267
|
```
|
254
268
|
|
269
|
+
### CVE-2016-3714 (ImageTragick)
|
270
|
+
This version of CarrierWave has the ability to mitigate CVE-2016-3714. However, you **MUST** set a content_type_whitelist in your uploaders for this protection to be effective, and you **MUST** either disable ImageMagick's default SVG delegate or use the RSVG delegate for SVG processing.
|
271
|
+
|
272
|
+
|
273
|
+
A valid whitelist that will restrict your uploader to images only, and mitigate the CVE is:
|
274
|
+
|
275
|
+
```ruby
|
276
|
+
class MyUploader < CarrierWave::Uploader::Base
|
277
|
+
def content_type_whitelist
|
278
|
+
[/image\//]
|
279
|
+
end
|
280
|
+
end
|
281
|
+
```
|
282
|
+
|
283
|
+
**WARNING**: A `content_type_whitelist` is the only form of whitelist or blacklist supported by CarrierWave that can effectively mitigate against CVE-2016-3714. Use of `extension_whitelist` will not inspect the file headers, and thus still leaves your application open to the vulnerability.
|
284
|
+
|
255
285
|
### Filenames and unicode chars
|
256
286
|
|
257
287
|
Another security issue you should care for is the file names (see
|
@@ -277,7 +307,7 @@ You no longer need to do this manually.
|
|
277
307
|
|
278
308
|
Often you'll want to add different versions of the same file. The classic example is image thumbnails. There is built in support for this*:
|
279
309
|
|
280
|
-
*Note:* You must have Imagemagick
|
310
|
+
*Note:* You must have Imagemagick installed to do image resizing.
|
281
311
|
|
282
312
|
Some documentation refers to RMagick instead of MiniMagick but MiniMagick is recommended.
|
283
313
|
|
@@ -359,7 +389,7 @@ private
|
|
359
389
|
end
|
360
390
|
|
361
391
|
def is_landscape? picture
|
362
|
-
image = MiniMagick::Image.
|
392
|
+
image = MiniMagick::Image.new(picture.path)
|
363
393
|
image[:width] > image[:height]
|
364
394
|
end
|
365
395
|
|
@@ -648,7 +678,6 @@ If you want to use fog you must add in your CarrierWave initializer the
|
|
648
678
|
following lines
|
649
679
|
|
650
680
|
```ruby
|
651
|
-
config.fog_provider = 'fog' # 'fog/aws' etc. Defaults to 'fog'
|
652
681
|
config.fog_credentials = { ... } # Provider specific credentials
|
653
682
|
```
|
654
683
|
|
@@ -666,7 +695,6 @@ You can also pass in additional options, as documented fully in lib/carrierwave/
|
|
666
695
|
|
667
696
|
```ruby
|
668
697
|
CarrierWave.configure do |config|
|
669
|
-
config.fog_provider = 'fog/aws' # required
|
670
698
|
config.fog_credentials = {
|
671
699
|
provider: 'AWS', # required
|
672
700
|
aws_access_key_id: 'xxx', # required unless using use_iam_profile
|
@@ -692,6 +720,14 @@ end
|
|
692
720
|
|
693
721
|
That's it! You can still use the `CarrierWave::Uploader#url` method to return the url to the file on Amazon S3.
|
694
722
|
|
723
|
+
**Note**: for Carrierwave to work properly it needs credentials with the following permissions:
|
724
|
+
|
725
|
+
* `s3:ListBucket`
|
726
|
+
* `s3:PutObject`
|
727
|
+
* `s3:GetObject`
|
728
|
+
* `s3:DeleteObject`
|
729
|
+
* `s3:PutObjectAcl`
|
730
|
+
|
695
731
|
## Using Rackspace Cloud Files
|
696
732
|
|
697
733
|
[Fog](http://github.com/fog/fog) is used to support Rackspace Cloud Files. Ensure you have it in your Gemfile:
|
@@ -707,7 +743,6 @@ Using a US-based account:
|
|
707
743
|
|
708
744
|
```ruby
|
709
745
|
CarrierWave.configure do |config|
|
710
|
-
config.fog_provider = "fog/rackspace/storage" # optional, defaults to "fog"
|
711
746
|
config.fog_credentials = {
|
712
747
|
provider: 'Rackspace',
|
713
748
|
rackspace_username: 'xxxxxx',
|
@@ -722,7 +757,6 @@ Using a UK-based account:
|
|
722
757
|
|
723
758
|
```ruby
|
724
759
|
CarrierWave.configure do |config|
|
725
|
-
config.fog_provider = "fog/rackspace/storage" # optional, defaults to "fog"
|
726
760
|
config.fog_credentials = {
|
727
761
|
provider: 'Rackspace',
|
728
762
|
rackspace_username: 'xxxxxx',
|
@@ -771,7 +805,6 @@ Please read the [fog-google README](https://github.com/fog/fog-google/blob/maste
|
|
771
805
|
|
772
806
|
```ruby
|
773
807
|
CarrierWave.configure do |config|
|
774
|
-
config.fog_provider = 'fog/google' # required
|
775
808
|
config.fog_credentials = {
|
776
809
|
provider: 'Google',
|
777
810
|
google_storage_access_key_id: 'xxxxxx',
|
@@ -868,8 +901,8 @@ manipulation methods.
|
|
868
901
|
|
869
902
|
## Using MiniMagick
|
870
903
|
|
871
|
-
MiniMagick is similar to RMagick but performs all the operations using the '
|
872
|
-
|
904
|
+
MiniMagick is similar to RMagick but performs all the operations using the 'convert'
|
905
|
+
CLI which is part of the standard ImageMagick kit. This allows you to have the power
|
873
906
|
of ImageMagick without having to worry about installing all the RMagick libraries.
|
874
907
|
|
875
908
|
See the MiniMagick site for more details:
|
data/lib/carrierwave.rb
CHANGED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
require 'addressable'
|
3
|
+
require 'carrierwave/downloader/remote_file'
|
4
|
+
|
5
|
+
module CarrierWave
|
6
|
+
module Downloader
|
7
|
+
class Base
|
8
|
+
attr_reader :uploader
|
9
|
+
|
10
|
+
def initialize(uploader)
|
11
|
+
@uploader = uploader
|
12
|
+
end
|
13
|
+
|
14
|
+
##
|
15
|
+
# Downloads a file from given URL and returns a RemoteFile.
|
16
|
+
#
|
17
|
+
# === Parameters
|
18
|
+
#
|
19
|
+
# [url (String)] The URL where the remote file is stored
|
20
|
+
# [remote_headers (Hash)] Request headers
|
21
|
+
#
|
22
|
+
def download(url, remote_headers = {})
|
23
|
+
headers = remote_headers.
|
24
|
+
reverse_merge('User-Agent' => "CarrierWave/#{CarrierWave::VERSION}")
|
25
|
+
begin
|
26
|
+
file = OpenURI.open_uri(process_uri(url.to_s), headers)
|
27
|
+
rescue StandardError => e
|
28
|
+
raise CarrierWave::DownloadError, "could not download file: #{e.message}"
|
29
|
+
end
|
30
|
+
CarrierWave::Downloader::RemoteFile.new(file)
|
31
|
+
end
|
32
|
+
|
33
|
+
##
|
34
|
+
# Processes the given URL by parsing and escaping it. Public to allow overriding.
|
35
|
+
#
|
36
|
+
# === Parameters
|
37
|
+
#
|
38
|
+
# [url (String)] The URL where the remote file is stored
|
39
|
+
#
|
40
|
+
def process_uri(uri)
|
41
|
+
uri_parts = uri.split('?')
|
42
|
+
encoded_uri = Addressable::URI.parse(uri_parts.shift).normalize.to_s
|
43
|
+
encoded_uri << '?' << URI.encode(uri_parts.join('?')) if uri_parts.any?
|
44
|
+
URI.parse(encoded_uri)
|
45
|
+
rescue URI::InvalidURIError, Addressable::URI::InvalidURIError
|
46
|
+
raise CarrierWave::DownloadError, "couldn't parse URL: #{uri}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module CarrierWave
|
2
|
+
module Downloader
|
3
|
+
class RemoteFile
|
4
|
+
attr_reader :file
|
5
|
+
|
6
|
+
def initialize(file)
|
7
|
+
@file = file.is_a?(String) ? StringIO.new(file) : file
|
8
|
+
end
|
9
|
+
|
10
|
+
def original_filename
|
11
|
+
filename = filename_from_header || filename_from_uri
|
12
|
+
mime_type = MiniMime.lookup_by_content_type(file.content_type)
|
13
|
+
unless File.extname(filename).present? || mime_type.blank?
|
14
|
+
filename = "#{filename}.#{mime_type.extension}"
|
15
|
+
end
|
16
|
+
filename
|
17
|
+
end
|
18
|
+
|
19
|
+
def respond_to?(*args)
|
20
|
+
super || file.respond_to?(*args)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def filename_from_header
|
26
|
+
if file.meta.include? 'content-disposition'
|
27
|
+
match = file.meta['content-disposition'].match(/filename=(?:"([^"]+)"|([^";]+))/)
|
28
|
+
match[1].presence || match[2].presence
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def filename_from_uri
|
33
|
+
CGI.unescape(File.basename(file.base_uri.path))
|
34
|
+
end
|
35
|
+
|
36
|
+
def method_missing(*args, &block)
|
37
|
+
file.send(*args, &block)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
data/lib/carrierwave/mount.rb
CHANGED
@@ -174,17 +174,26 @@ module CarrierWave
|
|
174
174
|
return if frozen?
|
175
175
|
mounter = _mounter(:#{column})
|
176
176
|
|
177
|
-
if mounter.remove?
|
178
|
-
|
179
|
-
elsif mounter.identifiers.first
|
180
|
-
write_uploader(mounter.serialization_column, mounter.identifiers.first)
|
181
|
-
end
|
177
|
+
mounter.clear! if mounter.remove?
|
178
|
+
write_uploader(mounter.serialization_column, mounter.identifiers.first)
|
182
179
|
end
|
183
180
|
|
184
181
|
def #{column}_identifier
|
185
182
|
_mounter(:#{column}).read_identifiers[0]
|
186
183
|
end
|
187
184
|
|
185
|
+
def #{column}_integrity_error
|
186
|
+
#{column}_integrity_errors.last
|
187
|
+
end
|
188
|
+
|
189
|
+
def #{column}_processing_error
|
190
|
+
#{column}_processing_errors.last
|
191
|
+
end
|
192
|
+
|
193
|
+
def #{column}_download_error
|
194
|
+
#{column}_download_errors.last
|
195
|
+
end
|
196
|
+
|
188
197
|
def store_previous_changes_for_#{column}
|
189
198
|
attribute_changes = ::ActiveRecord.version.to_s.to_f >= 5.1 ? saved_changes : changes
|
190
199
|
@_previous_changes_for_#{column} = attribute_changes[_mounter(:#{column}).serialization_column]
|
@@ -240,9 +249,9 @@ module CarrierWave
|
|
240
249
|
# [store_images!] Stores all files that have been assigned with +images=+
|
241
250
|
# [remove_images!] Removes the uploaded file from the filesystem.
|
242
251
|
#
|
243
|
-
# [
|
244
|
-
# [
|
245
|
-
# [
|
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
|
246
255
|
#
|
247
256
|
# [image_identifiers] Reads out the identifiers of the files
|
248
257
|
#
|
@@ -329,11 +338,8 @@ module CarrierWave
|
|
329
338
|
return if frozen?
|
330
339
|
mounter = _mounter(:#{column})
|
331
340
|
|
332
|
-
if mounter.remove?
|
333
|
-
|
334
|
-
elsif mounter.identifiers.any?
|
335
|
-
write_uploader(mounter.serialization_column, mounter.identifiers)
|
336
|
-
end
|
341
|
+
mounter.clear! if mounter.remove?
|
342
|
+
write_uploader(mounter.serialization_column, mounter.identifiers.presence)
|
337
343
|
end
|
338
344
|
|
339
345
|
def #{column}_identifiers
|
@@ -395,16 +401,16 @@ module CarrierWave
|
|
395
401
|
_mounter(:#{column}).store!
|
396
402
|
end
|
397
403
|
|
398
|
-
def #{column}
|
399
|
-
_mounter(:#{column}).
|
404
|
+
def #{column}_integrity_errors
|
405
|
+
_mounter(:#{column}).integrity_errors
|
400
406
|
end
|
401
407
|
|
402
|
-
def #{column}
|
403
|
-
_mounter(:#{column}).
|
408
|
+
def #{column}_processing_errors
|
409
|
+
_mounter(:#{column}).processing_errors
|
404
410
|
end
|
405
411
|
|
406
|
-
def #{column}
|
407
|
-
_mounter(:#{column}).
|
412
|
+
def #{column}_download_errors
|
413
|
+
_mounter(:#{column}).download_errors
|
408
414
|
end
|
409
415
|
|
410
416
|
def mark_remove_#{column}_false
|
data/lib/carrierwave/mounter.rb
CHANGED
@@ -3,14 +3,17 @@ module CarrierWave
|
|
3
3
|
# this is an internal class, used by CarrierWave::Mount so that
|
4
4
|
# we don't pollute the model with a lot of methods.
|
5
5
|
class Mounter #:nodoc:
|
6
|
-
attr_reader :column, :record, :remote_urls, :
|
7
|
-
:
|
6
|
+
attr_reader :column, :record, :remote_urls, :integrity_errors,
|
7
|
+
:processing_errors, :download_errors
|
8
8
|
attr_accessor :remove, :remote_request_headers
|
9
9
|
|
10
10
|
def initialize(record, column, options={})
|
11
11
|
@record = record
|
12
12
|
@column = column
|
13
13
|
@options = record.class.uploader_options[column]
|
14
|
+
@download_errors = []
|
15
|
+
@processing_errors = []
|
16
|
+
@integrity_errors = []
|
14
17
|
end
|
15
18
|
|
16
19
|
def uploader_class
|
@@ -38,21 +41,30 @@ module CarrierWave
|
|
38
41
|
end
|
39
42
|
|
40
43
|
def cache(new_files)
|
41
|
-
return if
|
44
|
+
return if !new_files.is_a?(Array) && new_files.blank?
|
45
|
+
old_uploaders = uploaders
|
42
46
|
@uploaders = new_files.map do |new_file|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
47
|
+
handle_error do
|
48
|
+
if new_file.is_a?(String)
|
49
|
+
if (uploader = old_uploaders.detect { |uploader| uploader.identifier == new_file })
|
50
|
+
uploader.staged = true
|
51
|
+
uploader
|
52
|
+
else
|
53
|
+
begin
|
54
|
+
uploader = blank_uploader
|
55
|
+
uploader.retrieve_from_cache!(new_file)
|
56
|
+
uploader
|
57
|
+
rescue CarrierWave::InvalidParameter
|
58
|
+
nil
|
59
|
+
end
|
60
|
+
end
|
61
|
+
else
|
62
|
+
uploader = blank_uploader
|
63
|
+
uploader.cache!(new_file)
|
64
|
+
uploader
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end.compact
|
56
68
|
end
|
57
69
|
|
58
70
|
def cache_names
|
@@ -60,45 +72,36 @@ module CarrierWave
|
|
60
72
|
end
|
61
73
|
|
62
74
|
def cache_names=(cache_names)
|
63
|
-
return if
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
75
|
+
return if cache_names.blank?
|
76
|
+
clear_unstaged
|
77
|
+
cache_names.map do |cache_name|
|
78
|
+
begin
|
79
|
+
uploader = blank_uploader
|
80
|
+
uploader.retrieve_from_cache!(cache_name)
|
81
|
+
@uploaders << uploader
|
82
|
+
rescue CarrierWave::InvalidParameter
|
83
|
+
# ignore
|
84
|
+
end
|
68
85
|
end
|
69
|
-
rescue CarrierWave::InvalidParameter
|
70
86
|
end
|
71
87
|
|
72
88
|
def remote_urls=(urls)
|
73
|
-
return if
|
89
|
+
return if urls.blank? || urls.all?(&:blank?)
|
74
90
|
|
75
91
|
@remote_urls = urls
|
76
|
-
@download_error = nil
|
77
|
-
@integrity_error = nil
|
78
92
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
93
|
+
clear_unstaged
|
94
|
+
urls.zip(remote_request_headers || []).map do |url, header|
|
95
|
+
handle_error do
|
96
|
+
uploader = blank_uploader
|
97
|
+
uploader.download!(url, header || {})
|
98
|
+
@uploaders << uploader
|
99
|
+
end
|
83
100
|
end
|
84
|
-
|
85
|
-
rescue CarrierWave::DownloadError => e
|
86
|
-
@download_error = e
|
87
|
-
raise e unless option(:ignore_download_errors)
|
88
|
-
rescue CarrierWave::ProcessingError => e
|
89
|
-
@processing_error = e
|
90
|
-
raise e unless option(:ignore_processing_errors)
|
91
|
-
rescue CarrierWave::IntegrityError => e
|
92
|
-
@integrity_error = e
|
93
|
-
raise e unless option(:ignore_integrity_errors)
|
94
101
|
end
|
95
102
|
|
96
103
|
def store!
|
97
|
-
|
98
|
-
remove!
|
99
|
-
else
|
100
|
-
uploaders.reject(&:blank?).each(&:store!)
|
101
|
-
end
|
104
|
+
uploaders.reject(&:blank?).each(&:store!)
|
102
105
|
end
|
103
106
|
|
104
107
|
def urls(*args)
|
@@ -118,6 +121,10 @@ module CarrierWave
|
|
118
121
|
@uploaders = []
|
119
122
|
end
|
120
123
|
|
124
|
+
def clear!
|
125
|
+
@uploaders = []
|
126
|
+
end
|
127
|
+
|
121
128
|
def serialization_column
|
122
129
|
option(:mount_on) || column
|
123
130
|
end
|
@@ -146,9 +153,7 @@ module CarrierWave
|
|
146
153
|
end.path
|
147
154
|
end
|
148
155
|
before.each do |uploader|
|
149
|
-
if uploader.remove_previously_stored_files_after_update
|
150
|
-
uploader.remove!
|
151
|
-
end
|
156
|
+
uploader.remove! if uploader.remove_previously_stored_files_after_update && !after_paths.include?(uploader.path)
|
152
157
|
end
|
153
158
|
end
|
154
159
|
|
@@ -161,5 +166,22 @@ module CarrierWave
|
|
161
166
|
self.uploader_options[name] ||= record.class.uploader_option(column, name)
|
162
167
|
end
|
163
168
|
|
169
|
+
def clear_unstaged
|
170
|
+
@uploaders ||= []
|
171
|
+
@uploaders.keep_if(&:staged)
|
172
|
+
end
|
173
|
+
|
174
|
+
def handle_error
|
175
|
+
yield
|
176
|
+
rescue CarrierWave::DownloadError => e
|
177
|
+
@download_errors << e
|
178
|
+
raise e unless option(:ignore_download_errors)
|
179
|
+
rescue CarrierWave::ProcessingError => e
|
180
|
+
@processing_errors << e
|
181
|
+
raise e unless option(:ignore_processing_errors)
|
182
|
+
rescue CarrierWave::IntegrityError => e
|
183
|
+
@integrity_errors << e
|
184
|
+
raise e unless option(:ignore_integrity_errors)
|
185
|
+
end
|
164
186
|
end # Mounter
|
165
187
|
end # CarrierWave
|