carrierwave 2.2.1 → 3.0.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.

Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +137 -67
  3. data/lib/carrierwave/compatibility/paperclip.rb +4 -2
  4. data/lib/carrierwave/downloader/base.rb +27 -13
  5. data/lib/carrierwave/downloader/remote_file.rb +12 -9
  6. data/lib/carrierwave/locale/en.yml +5 -3
  7. data/lib/carrierwave/mount.rb +31 -50
  8. data/lib/carrierwave/mounter.rb +115 -50
  9. data/lib/carrierwave/orm/activerecord.rb +14 -60
  10. data/lib/carrierwave/processing/mini_magick.rb +15 -13
  11. data/lib/carrierwave/processing/rmagick.rb +11 -15
  12. data/lib/carrierwave/processing/vips.rb +12 -12
  13. data/lib/carrierwave/sanitized_file.rb +49 -77
  14. data/lib/carrierwave/storage/abstract.rb +5 -5
  15. data/lib/carrierwave/storage/file.rb +6 -5
  16. data/lib/carrierwave/storage/fog.rb +75 -67
  17. data/lib/carrierwave/test/matchers.rb +11 -7
  18. data/lib/carrierwave/uploader/cache.rb +18 -10
  19. data/lib/carrierwave/uploader/callbacks.rb +1 -1
  20. data/lib/carrierwave/uploader/configuration.rb +10 -4
  21. data/lib/carrierwave/uploader/{content_type_whitelist.rb → content_type_allowlist.rb} +17 -15
  22. data/lib/carrierwave/uploader/{content_type_blacklist.rb → content_type_denylist.rb} +19 -14
  23. data/lib/carrierwave/uploader/dimension.rb +66 -0
  24. data/lib/carrierwave/uploader/{extension_whitelist.rb → extension_allowlist.rb} +17 -15
  25. data/lib/carrierwave/uploader/{extension_blacklist.rb → extension_denylist.rb} +18 -13
  26. data/lib/carrierwave/uploader/file_size.rb +2 -2
  27. data/lib/carrierwave/uploader/processing.rb +42 -7
  28. data/lib/carrierwave/uploader/proxy.rb +16 -3
  29. data/lib/carrierwave/uploader/store.rb +44 -6
  30. data/lib/carrierwave/uploader/url.rb +1 -1
  31. data/lib/carrierwave/uploader/versions.rb +150 -132
  32. data/lib/carrierwave/uploader.rb +10 -8
  33. data/lib/carrierwave/utilities/file_name.rb +47 -0
  34. data/lib/carrierwave/utilities/uri.rb +14 -11
  35. data/lib/carrierwave/utilities.rb +1 -0
  36. data/lib/carrierwave/validations/active_model.rb +4 -6
  37. data/lib/carrierwave/version.rb +1 -1
  38. data/lib/carrierwave.rb +9 -17
  39. data/lib/generators/uploader_generator.rb +3 -3
  40. metadata +31 -43
  41. /data/lib/generators/templates/{uploader.rb → uploader.rb.erb} +0 -0
@@ -11,7 +11,7 @@ module CarrierWave
11
11
  prepend Module.new {
12
12
  def initialize(*)
13
13
  super
14
- @file, @filename, @cache_id, @identifier = nil
14
+ @file, @filename, @cache_id, @identifier, @deduplication_index = nil
15
15
  end
16
16
  }
17
17
  end
@@ -34,9 +34,26 @@ module CarrierWave
34
34
  @filename
35
35
  end
36
36
 
37
+ ##
38
+ # Returns a filename which doesn't conflict with already-stored files.
39
+ #
40
+ # === Returns
41
+ #
42
+ # [String] the filename with suffix added for deduplication
43
+ #
44
+ def deduplicated_filename
45
+ return unless filename
46
+ return filename unless @deduplication_index
47
+
48
+ parts = filename.split('.')
49
+ basename = parts.shift
50
+ basename.sub!(/ ?\(\d+\)\z/, '')
51
+ ([basename.to_s + (@deduplication_index > 1 ? "(#{@deduplication_index})" : '')] + parts).join('.')
52
+ end
53
+
37
54
  ##
38
55
  # Calculates the path where the file should be stored. If +for_file+ is given, it will be
39
- # used as the filename, otherwise +CarrierWave::Uploader#filename+ is assumed.
56
+ # used as the identifier, otherwise +CarrierWave::Uploader#identifier+ is assumed.
40
57
  #
41
58
  # === Parameters
42
59
  #
@@ -46,7 +63,7 @@ module CarrierWave
46
63
  #
47
64
  # [String] the store path
48
65
  #
49
- def store_path(for_file=filename)
66
+ def store_path(for_file=identifier)
50
67
  File.join([store_dir, full_filename(for_file)].compact)
51
68
  end
52
69
 
@@ -60,7 +77,7 @@ module CarrierWave
60
77
  # [new_file (File, IOString, Tempfile)] any kind of file object
61
78
  #
62
79
  def store!(new_file=nil)
63
- cache!(new_file) if new_file && ((@cache_id != parent_cache_id) || @cache_id.nil?)
80
+ cache!(new_file) if new_file && !cached?
64
81
  if !cache_only && @file && @cache_id
65
82
  with_callbacks(:store, new_file) do
66
83
  new_file = storage.store!(@file)
@@ -69,7 +86,8 @@ module CarrierWave
69
86
  cache_storage.delete_dir!(cache_path(nil))
70
87
  end
71
88
  @file = new_file
72
- @cache_id = @identifier = nil
89
+ @identifier = storage.identifier
90
+ @cache_id = @deduplication_index = nil
73
91
  @staged = false
74
92
  end
75
93
  end
@@ -89,10 +107,30 @@ module CarrierWave
89
107
  end
90
108
  end
91
109
 
110
+ ##
111
+ # Look for a store path which doesn't collide with the given already-stored paths.
112
+ # It is done by adding a index number as the suffix.
113
+ # For example, if there's 'image.jpg' and the @deduplication_index is set to 2,
114
+ # The stored file will be named as 'image(2).jpg'.
115
+ #
116
+ # === Parameters
117
+ #
118
+ # [current_paths (Array[String])] List of paths for already-stored files
119
+ #
120
+ def deduplicate(current_paths)
121
+ @deduplication_index = nil
122
+ return unless current_paths.include?(store_path)
123
+
124
+ (1..current_paths.size + 1).each do |i|
125
+ @deduplication_index = i
126
+ break unless current_paths.include?(store_path)
127
+ end
128
+ end
129
+
92
130
  private
93
131
 
94
132
  def full_filename(for_file)
95
- for_file
133
+ forcing_extension(for_file)
96
134
  end
97
135
 
98
136
  def storage
@@ -23,7 +23,7 @@ module CarrierWave
23
23
  if file.respond_to?(:path)
24
24
  path = encode_path(file.path.sub(File.expand_path(root), ''))
25
25
 
26
- if host = asset_host
26
+ if (host = asset_host)
27
27
  if host.respond_to? :call
28
28
  "#{host.call(file)}#{path}"
29
29
  else
@@ -1,6 +1,89 @@
1
+ require "active_support/core_ext/object/deep_dup"
2
+
1
3
  module CarrierWave
2
4
  module Uploader
3
5
  module Versions
6
+ class Builder
7
+ def initialize(name)
8
+ @name = name
9
+ @options = {}
10
+ @blocks = []
11
+ @klass = nil
12
+ end
13
+
14
+ def configure(options, &block)
15
+ @options.merge!(options)
16
+ @blocks << block if block
17
+ @klass = nil
18
+ end
19
+
20
+ def build(superclass)
21
+ return @klass if @klass
22
+ @klass = Class.new(superclass)
23
+ superclass.const_set("#{@name.to_s.camelize}VersionUploader", @klass)
24
+
25
+ @klass.version_names += [@name]
26
+ @klass.versions = {}
27
+ @klass.processors = []
28
+ @klass.version_options = @options
29
+ @klass.class_eval <<-RUBY, __FILE__, __LINE__ + 1
30
+ # Define the enable_processing method for versions so they get the
31
+ # value from the parent class unless explicitly overwritten
32
+ def self.enable_processing(value=nil)
33
+ self.enable_processing = value if value
34
+ if defined?(@enable_processing) && !@enable_processing.nil?
35
+ @enable_processing
36
+ else
37
+ superclass.enable_processing
38
+ end
39
+ end
40
+
41
+ # Regardless of what is set in the parent uploader, do not enforce the
42
+ # move_to_cache config option on versions because it moves the original
43
+ # file to the version's target file.
44
+ #
45
+ # If you want to enforce this setting on versions, override this method
46
+ # in each version:
47
+ #
48
+ # version :thumb do
49
+ # def move_to_cache
50
+ # true
51
+ # end
52
+ # end
53
+ #
54
+ def move_to_cache
55
+ false
56
+ end
57
+
58
+ # Need to rely on the parent version's identifier, as versions don't have its own one.
59
+ def identifier
60
+ parent_version.identifier
61
+ end
62
+ RUBY
63
+ @blocks.each { |block| @klass.class_eval(&block) }
64
+ @klass
65
+ end
66
+
67
+ def deep_dup
68
+ other = dup
69
+ other.instance_variable_set(:@blocks, @blocks.dup)
70
+ other
71
+ end
72
+
73
+ def method_missing(name, *args)
74
+ super
75
+ rescue NoMethodError => e
76
+ raise e.exception <<~ERROR
77
+ #{e.message}
78
+ If you're trying to configure a version, do it inside a block like `version(:thumb) { self.#{name} #{args.map(&:inspect).join(', ')} }`.
79
+ ERROR
80
+ end
81
+
82
+ def respond_to_missing?(*)
83
+ super
84
+ end
85
+ end
86
+
4
87
  extend ActiveSupport::Concern
5
88
 
6
89
  include CarrierWave::Uploader::Callbacks
@@ -11,9 +94,8 @@ module CarrierWave
11
94
  self.versions = {}
12
95
  self.version_names = []
13
96
 
14
- attr_accessor :parent_cache_id, :parent_version
97
+ attr_accessor :parent_version
15
98
 
16
- after :cache, :assign_parent_cache_id
17
99
  after :cache, :cache_versions!
18
100
  after :store, :store_versions!
19
101
  after :remove, :remove_versions!
@@ -23,7 +105,7 @@ module CarrierWave
23
105
  prepend Module.new {
24
106
  def initialize(*)
25
107
  super
26
- @versions, @versions_to_cache, @versions_to_store = nil
108
+ @versions = nil
27
109
  end
28
110
  }
29
111
  end
@@ -51,80 +133,33 @@ module CarrierWave
51
133
  # process :scale => [200, 200]
52
134
  # end
53
135
  #
136
+ # version :square, :unless => :invalid_image_type? do
137
+ # process :scale => [100, 100]
138
+ # end
139
+ #
54
140
  # end
55
141
  #
56
142
  def version(name, options = {}, &block)
57
143
  name = name.to_sym
58
- build_version(name, options)
144
+ versions[name] ||= Builder.new(name)
145
+ versions[name].configure(options, &block)
59
146
 
60
- versions[name].class_eval(&block) if block
61
- versions[name]
62
- end
147
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
148
+ def #{name}
149
+ versions[:#{name}]
150
+ end
151
+ RUBY
63
152
 
64
- def recursively_apply_block_to_versions(&block)
65
- versions.each do |name, version|
66
- version.class_eval(&block)
67
- version.recursively_apply_block_to_versions(&block)
68
- end
153
+ versions[name]
69
154
  end
70
155
 
71
156
  private
72
157
 
73
- def build_version(name, options)
74
- if !versions.has_key?(name)
75
- uploader = Class.new(self)
76
- const_set("Uploader#{uploader.object_id}".tr('-', '_'), uploader)
77
- uploader.version_names += [name]
78
- uploader.versions = {}
79
- uploader.processors = []
80
- uploader.version_options = options
81
-
82
- uploader.class_eval <<-RUBY, __FILE__, __LINE__ + 1
83
- # Define the enable_processing method for versions so they get the
84
- # value from the parent class unless explicitly overwritten
85
- def self.enable_processing(value=nil)
86
- self.enable_processing = value if value
87
- if defined?(@enable_processing) && !@enable_processing.nil?
88
- @enable_processing
89
- else
90
- superclass.enable_processing
91
- end
92
- end
93
-
94
- # Regardless of what is set in the parent uploader, do not enforce the
95
- # move_to_cache config option on versions because it moves the original
96
- # file to the version's target file.
97
- #
98
- # If you want to enforce this setting on versions, override this method
99
- # in each version:
100
- #
101
- # version :thumb do
102
- # def move_to_cache
103
- # true
104
- # end
105
- # end
106
- #
107
- def move_to_cache
108
- false
109
- end
110
- RUBY
111
-
112
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
113
- def #{name}
114
- versions[:#{name}]
115
- end
116
- RUBY
117
- else
118
- uploader = Class.new(versions[name])
119
- const_set("Uploader#{uploader.object_id}".tr('-', '_'), uploader)
120
- uploader.processors = []
121
- uploader.version_options = uploader.version_options.merge(options)
122
- end
123
-
124
- # Add the current version hash to class attribute :versions
125
- self.versions = versions.merge(name => uploader)
158
+ def inherited(subclass)
159
+ # To prevent subclass version changes affecting superclass versions
160
+ subclass.versions = versions.deep_dup
161
+ super
126
162
  end
127
-
128
163
  end # ClassMethods
129
164
 
130
165
  ##
@@ -138,7 +173,7 @@ module CarrierWave
138
173
  return @versions if @versions
139
174
  @versions = {}
140
175
  self.class.versions.each do |name, version|
141
- @versions[name] = version.new(model, mounted_as)
176
+ @versions[name] = version.build(self.class).new(model, mounted_as)
142
177
  @versions[name].parent_version = self
143
178
  end
144
179
  @versions
@@ -161,25 +196,44 @@ module CarrierWave
161
196
  #
162
197
  # === Returns
163
198
  #
164
- # [Boolean] True when the version exists according to its :if condition
199
+ # [Boolean] True when the version exists according to its :if or :unless condition
165
200
  #
166
201
  def version_exists?(name)
167
202
  name = name.to_sym
168
203
 
169
- return false unless self.class.versions.has_key?(name)
204
+ return false unless versions.has_key?(name)
170
205
 
171
- condition = self.class.versions[name].version_options[:if]
172
- if(condition)
173
- if(condition.respond_to?(:call))
174
- condition.call(self, :version => name, :file => file)
206
+ if_condition = versions[name].class.version_options[:if]
207
+ unless_condition = versions[name].class.version_options[:unless]
208
+
209
+ if if_condition
210
+ if if_condition.respond_to?(:call)
211
+ if_condition.call(self, :version => name, :file => file)
212
+ else
213
+ send(if_condition, file)
214
+ end
215
+ elsif unless_condition
216
+ if unless_condition.respond_to?(:call)
217
+ !unless_condition.call(self, :version => name, :file => file)
175
218
  else
176
- send(condition, file)
219
+ !send(unless_condition, file)
177
220
  end
178
221
  else
179
222
  true
180
223
  end
181
224
  end
182
225
 
226
+ ##
227
+ # Copies the parent's cache_id when caching a version file.
228
+ # This behavior is not essential but it makes easier to understand
229
+ # that the cached files are generated by the single upload attempt.
230
+ #
231
+ def cache!(*args)
232
+ self.cache_id = parent_version.cache_id if parent_version
233
+
234
+ super
235
+ end
236
+
183
237
  ##
184
238
  # When given a version name as a parameter, will return the url for that version
185
239
  # This also works with nested versions.
@@ -221,60 +275,25 @@ module CarrierWave
221
275
  # versions if their parameters somehow have changed.
222
276
  #
223
277
  def recreate_versions!(*names)
224
- # Some files could possibly not be stored on the local disk. This
225
- # doesn't play nicely with processing. Make sure that we're only
226
- # processing a cached file
227
- #
228
- # The call to store! will trigger the necessary callbacks to both
229
- # process this version and all sub-versions
278
+ # As well as specified versions, we need to reprocess versions
279
+ # that are the source of another version.
230
280
 
231
- if names.any?
232
- set_versions_to_cache_and_store(names)
233
- store!(file)
234
- reset_versions_to_cache_and_store
235
- else
236
- cache! if !cached?
237
- store!
281
+ self.cache_id = CarrierWave.generate_cache_id
282
+ derived_versions.each do |name, v|
283
+ v.cache!(file) if names.empty? || !(v.descendant_version_names & names).empty?
238
284
  end
239
- end
240
-
241
- private
242
-
243
- def set_versions_to_cache_and_store(names)
244
- @versions_to_cache = source_versions_of(names)
245
- @versions_to_store = active_versions_with_names_in(@versions_to_cache + names)
246
- end
247
-
248
- def reset_versions_to_cache_and_store
249
- @versions_to_cache, @versions_to_store = nil, nil
250
- end
251
-
252
- def versions_to_cache
253
- @versions_to_cache || dependent_versions
254
- end
255
-
256
- def versions_to_store
257
- @versions_to_store || active_versions
258
- end
259
-
260
- def source_versions_of(requested_names)
261
- versions.inject([]) do |sources, (name, uploader)|
262
- next sources unless requested_names.include?(name)
263
- next sources unless source_name = uploader.class.version_options[:from_version]
264
-
265
- sources << [source_name, versions[source_name]]
266
- end.uniq
267
- end
268
-
269
- def active_versions_with_names_in(names)
270
- active_versions.select do |pretendent_name, uploader|
271
- names.include?(pretendent_name)
285
+ active_versions.each do |name, v|
286
+ v.store! if names.empty? || names.include?(name)
272
287
  end
288
+ ensure
289
+ @cache_id = nil
273
290
  end
274
291
 
275
- def assign_parent_cache_id(file)
276
- active_versions.each do |name, uploader|
277
- uploader.parent_cache_id = @cache_id
292
+ protected
293
+
294
+ def descendant_version_names
295
+ [version_name] + derived_versions.flat_map do |name, version|
296
+ version.descendant_version_names
278
297
  end
279
298
  end
280
299
 
@@ -284,16 +303,18 @@ module CarrierWave
284
303
  end
285
304
  end
286
305
 
287
- def dependent_versions
306
+ private
307
+
308
+ def derived_versions
288
309
  active_versions.reject do |name, v|
289
310
  v.class.version_options[:from_version]
290
- end.to_a + sibling_versions.select do |name, v|
311
+ end.to_a + active_sibling_versions.select do |name, v|
291
312
  v.class.version_options[:from_version] == self.class.version_names.last
292
313
  end.to_a
293
314
  end
294
315
 
295
- def sibling_versions
296
- parent_version.try(:versions) || []
316
+ def active_sibling_versions
317
+ parent_version&.active_versions || []
297
318
  end
298
319
 
299
320
  def full_filename(for_file)
@@ -305,14 +326,11 @@ module CarrierWave
305
326
  end
306
327
 
307
328
  def cache_versions!(new_file)
308
- versions_to_cache.each do |name, v|
309
- v.send(:cache_id=, @cache_id)
310
- v.cache!(new_file)
311
- end
329
+ derived_versions.each { |name, v| v.cache!(new_file) }
312
330
  end
313
331
 
314
332
  def store_versions!(new_file)
315
- versions_to_store.each { |name, v| v.store!(new_file) }
333
+ active_versions.each { |name, v| v.store!(new_file) }
316
334
  end
317
335
 
318
336
  def remove_versions!
@@ -7,11 +7,12 @@ require "carrierwave/uploader/cache"
7
7
  require "carrierwave/uploader/store"
8
8
  require "carrierwave/uploader/download"
9
9
  require "carrierwave/uploader/remove"
10
- require "carrierwave/uploader/extension_whitelist"
11
- require "carrierwave/uploader/extension_blacklist"
12
- require "carrierwave/uploader/content_type_whitelist"
13
- require "carrierwave/uploader/content_type_blacklist"
10
+ require "carrierwave/uploader/extension_allowlist"
11
+ require "carrierwave/uploader/extension_denylist"
12
+ require "carrierwave/uploader/content_type_allowlist"
13
+ require "carrierwave/uploader/content_type_denylist"
14
14
  require "carrierwave/uploader/file_size"
15
+ require "carrierwave/uploader/dimension"
15
16
  require "carrierwave/uploader/processing"
16
17
  require "carrierwave/uploader/versions"
17
18
  require "carrierwave/uploader/default_url"
@@ -52,11 +53,12 @@ module CarrierWave
52
53
  include CarrierWave::Uploader::Store
53
54
  include CarrierWave::Uploader::Download
54
55
  include CarrierWave::Uploader::Remove
55
- include CarrierWave::Uploader::ExtensionWhitelist
56
- include CarrierWave::Uploader::ExtensionBlacklist
57
- include CarrierWave::Uploader::ContentTypeWhitelist
58
- include CarrierWave::Uploader::ContentTypeBlacklist
56
+ include CarrierWave::Uploader::ExtensionAllowlist
57
+ include CarrierWave::Uploader::ExtensionDenylist
58
+ include CarrierWave::Uploader::ContentTypeAllowlist
59
+ include CarrierWave::Uploader::ContentTypeDenylist
59
60
  include CarrierWave::Uploader::FileSize
61
+ include CarrierWave::Uploader::Dimension
60
62
  include CarrierWave::Uploader::Processing
61
63
  include CarrierWave::Uploader::Versions
62
64
  include CarrierWave::Uploader::DefaultUrl
@@ -0,0 +1,47 @@
1
+ module CarrierWave
2
+ module Utilities
3
+ module FileName
4
+
5
+ ##
6
+ # Returns the part of the filename before the extension. So if a file is called 'test.jpeg'
7
+ # this would return 'test'
8
+ #
9
+ # === Returns
10
+ #
11
+ # [String] the first part of the filename
12
+ #
13
+ def basename
14
+ split_extension(filename)[0] if filename
15
+ end
16
+
17
+ ##
18
+ # Returns the file extension
19
+ #
20
+ # === Returns
21
+ #
22
+ # [String] extension of file or "" if the file has no extension
23
+ #
24
+ def extension
25
+ split_extension(filename)[1] if filename
26
+ end
27
+
28
+ private
29
+
30
+ def split_extension(filename)
31
+ # regular expressions to try for identifying extensions
32
+ extension_matchers = [
33
+ /\A(.+)\.(tar\.([glx]?z|bz2))\z/, # matches "something.tar.gz"
34
+ /\A(.+)\.([^\.]+)\z/ # matches "something.jpg"
35
+ ]
36
+
37
+ extension_matchers.each do |regexp|
38
+ if filename =~ regexp
39
+ return $1, $2
40
+ end
41
+ end
42
+
43
+ [filename, ""] # In case we weren't able to split the extension
44
+ end
45
+ end # FileName
46
+ end # Utilities
47
+ end # CarrierWave
@@ -3,20 +3,23 @@ require 'uri'
3
3
  module CarrierWave
4
4
  module Utilities
5
5
  module Uri
6
- # based on Ruby < 2.0's URI.encode
7
- SAFE_STRING = URI::REGEXP::PATTERN::UNRESERVED + '\/'
8
- UNSAFE = Regexp.new("[^#{SAFE_STRING}]", false)
6
+ # based on Ruby < 2.0's URI.encode
7
+ PATH_SAFE = URI::REGEXP::PATTERN::UNRESERVED + '\/'
8
+ PATH_UNSAFE = Regexp.new("[^#{PATH_SAFE}]", false)
9
+ NON_ASCII = /[^[:ascii:]]/.freeze
9
10
 
10
11
  private
12
+
11
13
  def encode_path(path)
12
- path.to_s.gsub(UNSAFE) do
13
- us = $&
14
- tmp = ''
15
- us.each_byte do |uc|
16
- tmp << sprintf('%%%02X', uc)
17
- end
18
- tmp
19
- end
14
+ URI::DEFAULT_PARSER.escape(path, PATH_UNSAFE)
15
+ end
16
+
17
+ def encode_non_ascii(str)
18
+ URI::DEFAULT_PARSER.escape(str, NON_ASCII)
19
+ end
20
+
21
+ def decode_uri(str)
22
+ URI::DEFAULT_PARSER.unescape(str)
20
23
  end
21
24
  end # Uri
22
25
  end # Utilities
@@ -1,4 +1,5 @@
1
1
  require 'carrierwave/utilities/uri'
2
+ require 'carrierwave/utilities/file_name'
2
3
 
3
4
  module CarrierWave
4
5
  module Utilities
@@ -12,8 +12,7 @@ module CarrierWave
12
12
 
13
13
  def validate_each(record, attribute, value)
14
14
  record.__send__("#{attribute}_processing_errors").each do |e|
15
- message = (e.message == e.class.to_s) ? :carrierwave_processing_error : e.message
16
- record.errors.add(attribute, message)
15
+ record.errors.add(attribute, :carrierwave_processing_error, message: (e.message != e.class.to_s) && e.message)
17
16
  end
18
17
  end
19
18
  end
@@ -22,8 +21,7 @@ module CarrierWave
22
21
 
23
22
  def validate_each(record, attribute, value)
24
23
  record.__send__("#{attribute}_integrity_errors").each do |e|
25
- message = (e.message == e.class.to_s) ? :carrierwave_integrity_error : e.message
26
- record.errors.add(attribute, message)
24
+ record.errors.add(attribute, :carrierwave_integrity_error, message: (e.message != e.class.to_s) && e.message)
27
25
  end
28
26
  end
29
27
  end
@@ -32,8 +30,7 @@ module CarrierWave
32
30
 
33
31
  def validate_each(record, attribute, value)
34
32
  record.__send__("#{attribute}_download_errors").each do |e|
35
- message = (e.message == e.class.to_s) ? :carrierwave_download_error : e.message
36
- record.errors.add(attribute, message)
33
+ record.errors.add(attribute, :carrierwave_download_error, message: (e.message != e.class.to_s) && e.message)
37
34
  end
38
35
  end
39
36
  end
@@ -58,6 +55,7 @@ module CarrierWave
58
55
  def validates_processing_of(*attr_names)
59
56
  validates_with ProcessingValidator, _merge_attributes(attr_names)
60
57
  end
58
+
61
59
  #
62
60
  ##
63
61
  # Makes the record invalid if the remote file couldn't be downloaded
@@ -1,3 +1,3 @@
1
1
  module CarrierWave
2
- VERSION = "2.2.1"
2
+ VERSION = "3.0.1".freeze
3
3
  end