carrierwave 0.9.0 → 3.0.2

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 (56) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +508 -158
  3. data/lib/carrierwave/compatibility/paperclip.rb +31 -21
  4. data/lib/carrierwave/downloader/base.rb +101 -0
  5. data/lib/carrierwave/downloader/remote_file.rb +68 -0
  6. data/lib/carrierwave/error.rb +1 -0
  7. data/lib/carrierwave/locale/en.yml +11 -5
  8. data/lib/carrierwave/mount.rb +220 -187
  9. data/lib/carrierwave/mounter.rb +255 -0
  10. data/lib/carrierwave/orm/activerecord.rb +24 -34
  11. data/lib/carrierwave/processing/mini_magick.rb +142 -79
  12. data/lib/carrierwave/processing/rmagick.rb +76 -35
  13. data/lib/carrierwave/processing/vips.rb +284 -0
  14. data/lib/carrierwave/processing.rb +1 -1
  15. data/lib/carrierwave/sanitized_file.rb +89 -70
  16. data/lib/carrierwave/storage/abstract.rb +16 -3
  17. data/lib/carrierwave/storage/file.rb +71 -3
  18. data/lib/carrierwave/storage/fog.rb +215 -58
  19. data/lib/carrierwave/storage.rb +1 -7
  20. data/lib/carrierwave/test/matchers.rb +88 -19
  21. data/lib/carrierwave/uploader/cache.rb +88 -44
  22. data/lib/carrierwave/uploader/callbacks.rb +1 -3
  23. data/lib/carrierwave/uploader/configuration.rb +81 -9
  24. data/lib/carrierwave/uploader/content_type_allowlist.rb +62 -0
  25. data/lib/carrierwave/uploader/content_type_denylist.rb +62 -0
  26. data/lib/carrierwave/uploader/default_url.rb +3 -5
  27. data/lib/carrierwave/uploader/dimension.rb +66 -0
  28. data/lib/carrierwave/uploader/download.rb +5 -69
  29. data/lib/carrierwave/uploader/extension_allowlist.rb +63 -0
  30. data/lib/carrierwave/uploader/extension_denylist.rb +64 -0
  31. data/lib/carrierwave/uploader/file_size.rb +43 -0
  32. data/lib/carrierwave/uploader/mountable.rb +13 -8
  33. data/lib/carrierwave/uploader/processing.rb +54 -21
  34. data/lib/carrierwave/uploader/proxy.rb +30 -8
  35. data/lib/carrierwave/uploader/remove.rb +0 -2
  36. data/lib/carrierwave/uploader/serialization.rb +3 -5
  37. data/lib/carrierwave/uploader/store.rb +59 -28
  38. data/lib/carrierwave/uploader/url.rb +8 -7
  39. data/lib/carrierwave/uploader/versions.rb +173 -124
  40. data/lib/carrierwave/uploader.rb +12 -6
  41. data/lib/carrierwave/utilities/file_name.rb +47 -0
  42. data/lib/carrierwave/utilities/uri.rb +14 -12
  43. data/lib/carrierwave/utilities.rb +2 -3
  44. data/lib/carrierwave/validations/active_model.rb +7 -13
  45. data/lib/carrierwave/version.rb +1 -1
  46. data/lib/carrierwave.rb +41 -16
  47. data/lib/generators/templates/{uploader.rb → uploader.rb.erb} +5 -9
  48. data/lib/generators/uploader_generator.rb +3 -3
  49. metadata +224 -100
  50. data/lib/carrierwave/locale/cs.yml +0 -11
  51. data/lib/carrierwave/locale/de.yml +0 -11
  52. data/lib/carrierwave/locale/nl.yml +0 -11
  53. data/lib/carrierwave/locale/sk.yml +0 -11
  54. data/lib/carrierwave/processing/mime_types.rb +0 -73
  55. data/lib/carrierwave/uploader/extension_blacklist.rb +0 -47
  56. data/lib/carrierwave/uploader/extension_whitelist.rb +0 -49
@@ -1,26 +1,113 @@
1
- # encoding: utf-8
1
+ require "active_support/core_ext/object/deep_dup"
2
2
 
3
3
  module CarrierWave
4
4
  module Uploader
5
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
+
6
87
  extend ActiveSupport::Concern
7
88
 
8
89
  include CarrierWave::Uploader::Callbacks
9
90
 
10
91
  included do
11
- class_attribute :versions, :version_names, :instance_reader => false, :instance_writer => false
92
+ class_attribute :versions, :version_names, :version_options, :instance_reader => false, :instance_writer => false
12
93
 
13
94
  self.versions = {}
14
95
  self.version_names = []
15
96
 
16
- attr_accessor :parent_cache_id
97
+ attr_accessor :parent_version
17
98
 
18
- after :cache, :assign_parent_cache_id
19
99
  after :cache, :cache_versions!
20
100
  after :store, :store_versions!
21
101
  after :remove, :remove_versions!
22
102
  after :retrieve_from_cache, :retrieve_versions_from_cache!
23
103
  after :retrieve_from_store, :retrieve_versions_from_store!
104
+
105
+ prepend Module.new {
106
+ def initialize(*)
107
+ super
108
+ @versions = nil
109
+ end
110
+ }
24
111
  end
25
112
 
26
113
  module ClassMethods
@@ -46,76 +133,32 @@ module CarrierWave
46
133
  # process :scale => [200, 200]
47
134
  # end
48
135
  #
136
+ # version :square, :unless => :invalid_image_type? do
137
+ # process :scale => [100, 100]
138
+ # end
139
+ #
49
140
  # end
50
141
  #
51
142
  def version(name, options = {}, &block)
52
143
  name = name.to_sym
53
- unless versions[name]
54
- uploader = Class.new(self)
55
- const_set("Uploader#{uploader.object_id}".gsub('-', '_'), uploader)
56
- uploader.versions = {}
57
-
58
- # Define the enable_processing method for versions so they get the
59
- # value from the parent class unless explicitly overwritten
60
- uploader.class_eval <<-RUBY, __FILE__, __LINE__ + 1
61
- def self.enable_processing(value=nil)
62
- self.enable_processing = value if value
63
- if !@enable_processing.nil?
64
- @enable_processing
65
- else
66
- superclass.enable_processing
67
- end
68
- end
69
- RUBY
70
-
71
- # Regardless of what is set in the parent uploader, do not enforce the
72
- # move_to_cache config option on versions because it moves the original
73
- # file to the version's target file.
74
- #
75
- # If you want to enforce this setting on versions, override this method
76
- # in each version:
77
- #
78
- # version :thumb do
79
- # def move_to_cache
80
- # true
81
- # end
82
- # end
83
- #
84
- uploader.class_eval <<-RUBY
85
- def move_to_cache
86
- false
87
- end
88
- RUBY
144
+ versions[name] ||= Builder.new(name)
145
+ versions[name].configure(options, &block)
89
146
 
90
- # Add the current version hash to class attribute :versions
91
- current_version = {}
92
- current_version[name] = {
93
- :uploader => uploader,
94
- :options => options
95
- }
96
- self.versions = versions.merge(current_version)
97
-
98
- versions[name][:uploader].version_names += [name]
147
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
148
+ def #{name}
149
+ versions[:#{name}]
150
+ end
151
+ RUBY
99
152
 
100
- class_eval <<-RUBY
101
- def #{name}
102
- versions[:#{name}]
103
- end
104
- RUBY
105
- # as the processors get the output from the previous processors as their
106
- # input we must not stack the processors here
107
- versions[name][:uploader].processors = versions[name][:uploader].processors.dup
108
- versions[name][:uploader].processors.clear
109
- end
110
- versions[name][:uploader].class_eval(&block) if block
111
153
  versions[name]
112
154
  end
113
155
 
114
- def recursively_apply_block_to_versions(&block)
115
- versions.each do |name, version|
116
- version[:uploader].class_eval(&block)
117
- version[:uploader].recursively_apply_block_to_versions(&block)
118
- end
156
+ private
157
+
158
+ def inherited(subclass)
159
+ # To prevent subclass version changes affecting superclass versions
160
+ subclass.versions = versions.deep_dup
161
+ super
119
162
  end
120
163
  end # ClassMethods
121
164
 
@@ -130,7 +173,8 @@ module CarrierWave
130
173
  return @versions if @versions
131
174
  @versions = {}
132
175
  self.class.versions.each do |name, version|
133
- @versions[name] = version[:uploader].new(model, mounted_as)
176
+ @versions[name] = version.build(self.class).new(model, mounted_as)
177
+ @versions[name].parent_version = self
134
178
  end
135
179
  @versions
136
180
  end
@@ -152,25 +196,44 @@ module CarrierWave
152
196
  #
153
197
  # === Returns
154
198
  #
155
- # [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
156
200
  #
157
201
  def version_exists?(name)
158
202
  name = name.to_sym
159
203
 
160
- return false unless self.class.versions.has_key?(name)
204
+ return false unless versions.has_key?(name)
205
+
206
+ if_condition = versions[name].class.version_options[:if]
207
+ unless_condition = versions[name].class.version_options[:unless]
161
208
 
162
- condition = self.class.versions[name][:options][:if]
163
- if(condition)
164
- if(condition.respond_to?(:call))
165
- condition.call(self, :version => name, :file => file)
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)
166
218
  else
167
- send(condition, file)
219
+ !send(unless_condition, file)
168
220
  end
169
221
  else
170
222
  true
171
223
  end
172
224
  end
173
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
+
174
237
  ##
175
238
  # When given a version name as a parameter, will return the url for that version
176
239
  # This also works with nested versions.
@@ -199,7 +262,7 @@ module CarrierWave
199
262
  if (version = args.first) && version.respond_to?(:to_sym)
200
263
  raise ArgumentError, "Version #{version} doesn't exist!" if versions[version.to_sym].nil?
201
264
  # recursively proxy to version
202
- versions[version.to_sym].url(*args[1..-1]) if version_exists?(version)
265
+ versions[version.to_sym].url(*args[1..-1])
203
266
  elsif args.first
204
267
  super(args.first)
205
268
  else
@@ -211,26 +274,26 @@ module CarrierWave
211
274
  # Recreate versions and reprocess them. This can be used to recreate
212
275
  # versions if their parameters somehow have changed.
213
276
  #
214
- def recreate_versions!(*versions)
215
- # Some files could possibly not be stored on the local disk. This
216
- # doesn't play nicely with processing. Make sure that we're only
217
- # processing a cached file
218
- #
219
- # The call to store! will trigger the necessary callbacks to both
220
- # process this version and all sub-versions
221
- if versions.any?
222
- file = sanitized_file if !cached?
223
- store_versions!(file, versions)
224
- else
225
- cache! if !cached?
226
- store!
277
+ def recreate_versions!(*names)
278
+ # As well as specified versions, we need to reprocess versions
279
+ # that are the source of another version.
280
+
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?
227
284
  end
285
+ active_versions.each do |name, v|
286
+ v.store! if names.empty? || names.include?(name)
287
+ end
288
+ ensure
289
+ @cache_id = nil
228
290
  end
229
291
 
230
- private
231
- def assign_parent_cache_id(file)
232
- active_versions.each do |name, uploader|
233
- 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
234
297
  end
235
298
  end
236
299
 
@@ -240,6 +303,20 @@ module CarrierWave
240
303
  end
241
304
  end
242
305
 
306
+ private
307
+
308
+ def derived_versions
309
+ active_versions.reject do |name, v|
310
+ v.class.version_options[:from_version]
311
+ end.to_a + active_sibling_versions.select do |name, v|
312
+ v.class.version_options[:from_version] == self.class.version_names.last
313
+ end.to_a
314
+ end
315
+
316
+ def active_sibling_versions
317
+ parent_version&.active_versions || []
318
+ end
319
+
243
320
  def full_filename(for_file)
244
321
  [version_name, super(for_file)].compact.join('_')
245
322
  end
@@ -249,39 +326,11 @@ module CarrierWave
249
326
  end
250
327
 
251
328
  def cache_versions!(new_file)
252
- # We might have processed the new_file argument after the callbacks were
253
- # initialized, so get the actual file based off of the current state of
254
- # our file
255
- processed_parent = SanitizedFile.new :tempfile => self.file,
256
- :filename => new_file.original_filename
257
-
258
- active_versions.each do |name, v|
259
- next if v.cached?
260
-
261
- v.send(:cache_id=, cache_id)
262
- # If option :from_version is present, create cache using cached file from
263
- # version indicated
264
- if self.class.versions[name][:options] && self.class.versions[name][:options][:from_version]
265
- # Maybe the reference version has not been cached yet
266
- unless versions[self.class.versions[name][:options][:from_version]].cached?
267
- versions[self.class.versions[name][:options][:from_version]].cache!(processed_parent)
268
- end
269
- processed_version = SanitizedFile.new :tempfile => versions[self.class.versions[name][:options][:from_version]],
270
- :filename => new_file.original_filename
271
- v.cache!(processed_version)
272
- else
273
- v.cache!(processed_parent)
274
- end
275
- end
329
+ derived_versions.each { |name, v| v.cache!(new_file) }
276
330
  end
277
331
 
278
- def store_versions!(new_file, versions=nil)
279
- if versions
280
- active = Hash[active_versions]
281
- versions.each { |v| active[v].try(:store!, new_file) } unless active.empty?
282
- else
283
- active_versions.each { |name, v| v.store!(new_file) }
284
- end
332
+ def store_versions!(new_file)
333
+ active_versions.each { |name, v| v.store!(new_file) }
285
334
  end
286
335
 
287
336
  def remove_versions!
@@ -289,11 +338,11 @@ module CarrierWave
289
338
  end
290
339
 
291
340
  def retrieve_versions_from_cache!(cache_name)
292
- versions.each { |name, v| v.retrieve_from_cache!(cache_name) }
341
+ active_versions.each { |name, v| v.retrieve_from_cache!(cache_name) }
293
342
  end
294
343
 
295
344
  def retrieve_versions_from_store!(identifier)
296
- versions.each { |name, v| v.retrieve_from_store!(identifier) }
345
+ active_versions.each { |name, v| v.retrieve_from_store!(identifier) }
297
346
  end
298
347
 
299
348
  end # Versions
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  require "carrierwave/uploader/configuration"
4
2
  require "carrierwave/uploader/callbacks"
5
3
  require "carrierwave/uploader/proxy"
@@ -9,8 +7,12 @@ require "carrierwave/uploader/cache"
9
7
  require "carrierwave/uploader/store"
10
8
  require "carrierwave/uploader/download"
11
9
  require "carrierwave/uploader/remove"
12
- require "carrierwave/uploader/extension_whitelist"
13
- require "carrierwave/uploader/extension_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
+ require "carrierwave/uploader/file_size"
15
+ require "carrierwave/uploader/dimension"
14
16
  require "carrierwave/uploader/processing"
15
17
  require "carrierwave/uploader/versions"
16
18
  require "carrierwave/uploader/default_url"
@@ -51,8 +53,12 @@ module CarrierWave
51
53
  include CarrierWave::Uploader::Store
52
54
  include CarrierWave::Uploader::Download
53
55
  include CarrierWave::Uploader::Remove
54
- include CarrierWave::Uploader::ExtensionWhitelist
55
- include CarrierWave::Uploader::ExtensionBlacklist
56
+ include CarrierWave::Uploader::ExtensionAllowlist
57
+ include CarrierWave::Uploader::ExtensionDenylist
58
+ include CarrierWave::Uploader::ContentTypeAllowlist
59
+ include CarrierWave::Uploader::ContentTypeDenylist
60
+ include CarrierWave::Uploader::FileSize
61
+ include CarrierWave::Uploader::Dimension
56
62
  include CarrierWave::Uploader::Processing
57
63
  include CarrierWave::Uploader::Versions
58
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
@@ -1,23 +1,25 @@
1
- # encoding: utf-8
1
+ require 'uri'
2
2
 
3
3
  module CarrierWave
4
4
  module Utilities
5
5
  module Uri
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
6
10
 
7
11
  private
12
+
8
13
  def encode_path(path)
9
- # based on Ruby < 2.0's URI.encode
10
- safe_string = URI::REGEXP::PATTERN::UNRESERVED + '\/'
11
- unsafe = Regexp.new("[^#{safe_string}]", false)
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
12
20
 
13
- path.to_s.gsub(unsafe) do
14
- us = $&
15
- tmp = ''
16
- us.each_byte do |uc|
17
- tmp << sprintf('%%%02X', uc)
18
- end
19
- tmp
20
- end
21
+ def decode_uri(str)
22
+ URI::DEFAULT_PARSER.unescape(str)
21
23
  end
22
24
  end # Uri
23
25
  end # Utilities
@@ -1,8 +1,7 @@
1
- # encoding: utf-8
2
-
3
1
  require 'carrierwave/utilities/uri'
2
+ require 'carrierwave/utilities/file_name'
4
3
 
5
4
  module CarrierWave
6
5
  module Utilities
7
6
  end
8
- end
7
+ end
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  require 'active_model/validator'
4
2
  require 'active_support/concern'
5
3
 
@@ -13,9 +11,8 @@ module CarrierWave
13
11
  class ProcessingValidator < ::ActiveModel::EachValidator
14
12
 
15
13
  def validate_each(record, attribute, value)
16
- if e = record.send("#{attribute}_processing_error")
17
- message = (e.message == e.class.to_s) ? :carrierwave_processing_error : e.message
18
- record.errors.add(attribute, message)
14
+ record.__send__("#{attribute}_processing_errors").each do |e|
15
+ record.errors.add(attribute, :carrierwave_processing_error, message: (e.message != e.class.to_s) && e.message)
19
16
  end
20
17
  end
21
18
  end
@@ -23,9 +20,8 @@ module CarrierWave
23
20
  class IntegrityValidator < ::ActiveModel::EachValidator
24
21
 
25
22
  def validate_each(record, attribute, value)
26
- if e = record.send("#{attribute}_integrity_error")
27
- message = (e.message == e.class.to_s) ? :carrierwave_integrity_error : e.message
28
- record.errors.add(attribute, message)
23
+ record.__send__("#{attribute}_integrity_errors").each do |e|
24
+ record.errors.add(attribute, :carrierwave_integrity_error, message: (e.message != e.class.to_s) && e.message)
29
25
  end
30
26
  end
31
27
  end
@@ -33,9 +29,8 @@ module CarrierWave
33
29
  class DownloadValidator < ::ActiveModel::EachValidator
34
30
 
35
31
  def validate_each(record, attribute, value)
36
- if e = record.send("#{attribute}_download_error")
37
- message = (e.message == e.class.to_s) ? :carrierwave_download_error : e.message
38
- record.errors.add(attribute, message)
32
+ record.__send__("#{attribute}_download_errors").each do |e|
33
+ record.errors.add(attribute, :carrierwave_download_error, message: (e.message != e.class.to_s) && e.message)
39
34
  end
40
35
  end
41
36
  end
@@ -60,6 +55,7 @@ module CarrierWave
60
55
  def validates_processing_of(*attr_names)
61
56
  validates_with ProcessingValidator, _merge_attributes(attr_names)
62
57
  end
58
+
63
59
  #
64
60
  ##
65
61
  # Makes the record invalid if the remote file couldn't be downloaded
@@ -78,5 +74,3 @@ module CarrierWave
78
74
  end
79
75
  end
80
76
  end
81
-
82
- I18n.load_path << File.join(File.dirname(__FILE__), "..", "locale", 'en.yml')
@@ -1,3 +1,3 @@
1
1
  module CarrierWave
2
- VERSION = "0.9.0"
2
+ VERSION = "3.0.2".freeze
3
3
  end