carrierwave 0.11.2 → 2.1.0

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 (60) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +294 -124
  3. data/lib/carrierwave.rb +34 -8
  4. data/lib/carrierwave/compatibility/paperclip.rb +0 -2
  5. data/lib/carrierwave/downloader/base.rb +50 -0
  6. data/lib/carrierwave/downloader/remote_file.rb +44 -0
  7. data/lib/carrierwave/error.rb +1 -0
  8. data/lib/carrierwave/locale/en.yml +7 -4
  9. data/lib/carrierwave/mount.rb +229 -180
  10. data/lib/carrierwave/mounter.rb +188 -0
  11. data/lib/carrierwave/orm/activerecord.rb +59 -24
  12. data/lib/carrierwave/processing.rb +0 -1
  13. data/lib/carrierwave/processing/mini_magick.rb +137 -83
  14. data/lib/carrierwave/processing/rmagick.rb +54 -5
  15. data/lib/carrierwave/sanitized_file.rb +50 -30
  16. data/lib/carrierwave/storage.rb +1 -9
  17. data/lib/carrierwave/storage/abstract.rb +15 -2
  18. data/lib/carrierwave/storage/file.rb +69 -2
  19. data/lib/carrierwave/storage/fog.rb +177 -37
  20. data/lib/carrierwave/test/matchers.rb +77 -12
  21. data/lib/carrierwave/uploader.rb +2 -2
  22. data/lib/carrierwave/uploader/cache.rb +60 -38
  23. data/lib/carrierwave/uploader/callbacks.rb +0 -2
  24. data/lib/carrierwave/uploader/configuration.rb +71 -13
  25. data/lib/carrierwave/uploader/content_type_whitelist.rb +1 -1
  26. data/lib/carrierwave/uploader/default_url.rb +3 -5
  27. data/lib/carrierwave/uploader/download.rb +4 -74
  28. data/lib/carrierwave/uploader/extension_blacklist.rb +14 -10
  29. data/lib/carrierwave/uploader/extension_whitelist.rb +13 -10
  30. data/lib/carrierwave/uploader/file_size.rb +43 -0
  31. data/lib/carrierwave/uploader/mountable.rb +13 -8
  32. data/lib/carrierwave/uploader/processing.rb +10 -10
  33. data/lib/carrierwave/uploader/proxy.rb +6 -8
  34. data/lib/carrierwave/uploader/remove.rb +0 -2
  35. data/lib/carrierwave/uploader/serialization.rb +2 -4
  36. data/lib/carrierwave/uploader/store.rb +17 -24
  37. data/lib/carrierwave/uploader/url.rb +3 -5
  38. data/lib/carrierwave/uploader/versions.rb +123 -93
  39. data/lib/carrierwave/utilities.rb +0 -3
  40. data/lib/carrierwave/utilities/uri.rb +5 -6
  41. data/lib/carrierwave/validations/active_model.rb +3 -5
  42. data/lib/carrierwave/version.rb +1 -1
  43. data/lib/generators/templates/uploader.rb +4 -8
  44. metadata +80 -65
  45. data/lib/carrierwave/locale/cs.yml +0 -11
  46. data/lib/carrierwave/locale/de.yml +0 -11
  47. data/lib/carrierwave/locale/el.yml +0 -11
  48. data/lib/carrierwave/locale/es.yml +0 -11
  49. data/lib/carrierwave/locale/fr.yml +0 -11
  50. data/lib/carrierwave/locale/ja.yml +0 -11
  51. data/lib/carrierwave/locale/nb.yml +0 -11
  52. data/lib/carrierwave/locale/nl.yml +0 -11
  53. data/lib/carrierwave/locale/pl.yml +0 -11
  54. data/lib/carrierwave/locale/pt-BR.yml +0 -11
  55. data/lib/carrierwave/locale/pt-PT.yml +0 -11
  56. data/lib/carrierwave/locale/ru.yml +0 -11
  57. data/lib/carrierwave/locale/sk.yml +0 -11
  58. data/lib/carrierwave/locale/tr.yml +0 -11
  59. data/lib/carrierwave/processing/mime_types.rb +0 -74
  60. data/lib/carrierwave/utilities/deprecation.rb +0 -18
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module CarrierWave
4
2
  module Uploader
5
3
  module Store
@@ -9,6 +7,15 @@ module CarrierWave
9
7
  include CarrierWave::Uploader::Configuration
10
8
  include CarrierWave::Uploader::Cache
11
9
 
10
+ included do
11
+ prepend Module.new {
12
+ def initialize(*)
13
+ super
14
+ @file, @filename, @cache_id, @identifier = nil
15
+ end
16
+ }
17
+ end
18
+
12
19
  ##
13
20
  # Override this in your Uploader to change the filename.
14
21
  #
@@ -54,31 +61,16 @@ module CarrierWave
54
61
  #
55
62
  def store!(new_file=nil)
56
63
  cache!(new_file) if new_file && ((@cache_id != parent_cache_id) || @cache_id.nil?)
57
- if @file and @cache_id
64
+ if !cache_only && @file && @cache_id
58
65
  with_callbacks(:store, new_file) do
59
66
  new_file = storage.store!(@file)
60
- @file.delete if (delete_tmp_file_after_storage && ! move_to_store)
61
- delete_cache_id
67
+ if delete_tmp_file_after_storage
68
+ @file.delete unless move_to_store
69
+ cache_storage.delete_dir!(cache_path(nil))
70
+ end
62
71
  @file = new_file
63
- @cache_id = nil
64
- end
65
- end
66
- end
67
-
68
- ##
69
- # Deletes a cache id (tmp dir in cache)
70
- #
71
- def delete_cache_id
72
- if @cache_id
73
- path = File.expand_path(File.join(cache_dir, @cache_id), CarrierWave.root)
74
- begin
75
- Dir.rmdir(path)
76
- rescue Errno::ENOENT
77
- # Ignore: path does not exist
78
- rescue Errno::ENOTDIR
79
- # Ignore: path is not a dir
80
- rescue Errno::ENOTEMPTY, Errno::EEXIST
81
- # Ignore: dir is not empty
72
+ @cache_id = @identifier = nil
73
+ @staged = false
82
74
  end
83
75
  end
84
76
  end
@@ -93,6 +85,7 @@ module CarrierWave
93
85
  def retrieve_from_store!(identifier)
94
86
  with_callbacks(:retrieve_from_store, identifier) do
95
87
  @file = storage.retrieve!(identifier)
88
+ @identifier = identifier
96
89
  end
97
90
  end
98
91
 
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module CarrierWave
4
2
  module Uploader
5
3
  module Url
@@ -17,10 +15,10 @@ module CarrierWave
17
15
  # [String] the location where this file is accessible via a url
18
16
  #
19
17
  def url(options = {})
20
- if file.respond_to?(:url) and not file.url.blank?
21
- file.method(:url).arity == 0 ? file.url : file.url(options)
18
+ if file.respond_to?(:url) && !(tmp_url = file.url).blank?
19
+ file.method(:url).arity.zero? ? tmp_url : file.url(options)
22
20
  elsif file.respond_to?(:path)
23
- path = encode_path(file.path.gsub(File.expand_path(root), ''))
21
+ path = encode_path(file.path.sub(File.expand_path(root), ''))
24
22
 
25
23
  if host = asset_host
26
24
  if host.respond_to? :call
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module CarrierWave
4
2
  module Uploader
5
3
  module Versions
@@ -8,12 +6,12 @@ module CarrierWave
8
6
  include CarrierWave::Uploader::Callbacks
9
7
 
10
8
  included do
11
- class_attribute :versions, :version_names, :instance_reader => false, :instance_writer => false
9
+ class_attribute :versions, :version_names, :version_options, :instance_reader => false, :instance_writer => false
12
10
 
13
11
  self.versions = {}
14
12
  self.version_names = []
15
13
 
16
- attr_accessor :parent_cache_id
14
+ attr_accessor :parent_cache_id, :parent_version
17
15
 
18
16
  after :cache, :assign_parent_cache_id
19
17
  after :cache, :cache_versions!
@@ -21,6 +19,13 @@ module CarrierWave
21
19
  after :remove, :remove_versions!
22
20
  after :retrieve_from_cache, :retrieve_versions_from_cache!
23
21
  after :retrieve_from_store, :retrieve_versions_from_store!
22
+
23
+ prepend Module.new {
24
+ def initialize(*)
25
+ super
26
+ @versions = nil
27
+ end
28
+ }
24
29
  end
25
30
 
26
31
  module ClassMethods
@@ -50,72 +55,74 @@ module CarrierWave
50
55
  #
51
56
  def version(name, options = {}, &block)
52
57
  name = name.to_sym
53
- build_version(name, options) unless versions[name]
58
+ build_version(name, options)
54
59
 
55
- versions[name][:uploader].class_eval(&block) if block
60
+ versions[name].class_eval(&block) if block
56
61
  versions[name]
57
62
  end
58
63
 
59
64
  def recursively_apply_block_to_versions(&block)
60
65
  versions.each do |name, version|
61
- version[:uploader].class_eval(&block)
62
- version[:uploader].recursively_apply_block_to_versions(&block)
66
+ version.class_eval(&block)
67
+ version.recursively_apply_block_to_versions(&block)
63
68
  end
64
69
  end
65
70
 
66
71
  private
67
72
 
68
73
  def build_version(name, options)
69
- uploader = Class.new(self)
70
- const_set("Uploader#{uploader.object_id}".gsub('-', '_'), uploader)
71
- uploader.version_names += [name]
72
- uploader.versions = {}
73
- uploader.processors = []
74
-
75
- uploader.class_eval <<-RUBY, __FILE__, __LINE__ + 1
76
- # Define the enable_processing method for versions so they get the
77
- # value from the parent class unless explicitly overwritten
78
- def self.enable_processing(value=nil)
79
- self.enable_processing = value if value
80
- if !@enable_processing.nil?
81
- @enable_processing
82
- else
83
- superclass.enable_processing
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
84
109
  end
85
- end
86
-
87
- # Regardless of what is set in the parent uploader, do not enforce the
88
- # move_to_cache config option on versions because it moves the original
89
- # file to the version's target file.
90
- #
91
- # If you want to enforce this setting on versions, override this method
92
- # in each version:
93
- #
94
- # version :thumb do
95
- # def move_to_cache
96
- # true
97
- # end
98
- # end
99
- #
100
- def move_to_cache
101
- false
102
- end
103
- RUBY
104
-
105
- class_eval <<-RUBY
106
- def #{name}
107
- versions[:#{name}]
108
- end
109
- RUBY
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
110
123
 
111
124
  # Add the current version hash to class attribute :versions
112
- current_version = {
113
- name => {
114
- :uploader => uploader,
115
- :options => options
116
- }
117
- }
118
- self.versions = versions.merge(current_version)
125
+ self.versions = versions.merge(name => uploader)
119
126
  end
120
127
 
121
128
  end # ClassMethods
@@ -131,7 +138,8 @@ module CarrierWave
131
138
  return @versions if @versions
132
139
  @versions = {}
133
140
  self.class.versions.each do |name, version|
134
- @versions[name] = version[:uploader].new(model, mounted_as)
141
+ @versions[name] = version.new(model, mounted_as)
142
+ @versions[name].parent_version = self
135
143
  end
136
144
  @versions
137
145
  end
@@ -160,7 +168,7 @@ module CarrierWave
160
168
 
161
169
  return false unless self.class.versions.has_key?(name)
162
170
 
163
- condition = self.class.versions[name][:options][:if]
171
+ condition = self.class.versions[name].version_options[:if]
164
172
  if(condition)
165
173
  if(condition.respond_to?(:call))
166
174
  condition.call(self, :version => name, :file => file)
@@ -212,16 +220,18 @@ module CarrierWave
212
220
  # Recreate versions and reprocess them. This can be used to recreate
213
221
  # versions if their parameters somehow have changed.
214
222
  #
215
- def recreate_versions!(*versions)
223
+ def recreate_versions!(*names)
216
224
  # Some files could possibly not be stored on the local disk. This
217
225
  # doesn't play nicely with processing. Make sure that we're only
218
226
  # processing a cached file
219
227
  #
220
228
  # The call to store! will trigger the necessary callbacks to both
221
229
  # process this version and all sub-versions
222
- if versions.any?
223
- file = sanitized_file if !cached?
224
- store_versions!(file, versions)
230
+
231
+ if names.any?
232
+ set_versions_to_cache_and_store(names)
233
+ store!(file)
234
+ reset_versions_to_cache_and_store
225
235
  else
226
236
  cache! if !cached?
227
237
  store!
@@ -229,6 +239,39 @@ module CarrierWave
229
239
  end
230
240
 
231
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)
272
+ end
273
+ end
274
+
232
275
  def assign_parent_cache_id(file)
233
276
  active_versions.each do |name, uploader|
234
277
  uploader.parent_cache_id = @cache_id
@@ -241,6 +284,18 @@ module CarrierWave
241
284
  end
242
285
  end
243
286
 
287
+ def dependent_versions
288
+ active_versions.reject do |name, v|
289
+ v.class.version_options[:from_version]
290
+ end.to_a + sibling_versions.select do |name, v|
291
+ v.class.version_options[:from_version] == self.class.version_names.last
292
+ end.to_a
293
+ end
294
+
295
+ def sibling_versions
296
+ parent_version.try(:versions) || []
297
+ end
298
+
244
299
  def full_filename(for_file)
245
300
  [version_name, super(for_file)].compact.join('_')
246
301
  end
@@ -250,39 +305,14 @@ module CarrierWave
250
305
  end
251
306
 
252
307
  def cache_versions!(new_file)
253
- # We might have processed the new_file argument after the callbacks were
254
- # initialized, so get the actual file based off of the current state of
255
- # our file
256
- processed_parent = SanitizedFile.new :tempfile => self.file,
257
- :filename => new_file.original_filename
258
-
259
- active_versions.each do |name, v|
260
- next if v.cached?
261
-
262
- v.send(:cache_id=, cache_id)
263
- # If option :from_version is present, create cache using cached file from
264
- # version indicated
265
- if self.class.versions[name][:options] && self.class.versions[name][:options][:from_version]
266
- # Maybe the reference version has not been cached yet
267
- unless versions[self.class.versions[name][:options][:from_version]].cached?
268
- versions[self.class.versions[name][:options][:from_version]].cache!(processed_parent)
269
- end
270
- processed_version = SanitizedFile.new :tempfile => versions[self.class.versions[name][:options][:from_version]],
271
- :filename => new_file.original_filename
272
- v.cache!(processed_version)
273
- else
274
- v.cache!(processed_parent)
275
- end
308
+ versions_to_cache.each do |name, v|
309
+ v.send(:cache_id=, @cache_id)
310
+ v.cache!(new_file)
276
311
  end
277
312
  end
278
313
 
279
- def store_versions!(new_file, versions=nil)
280
- if versions
281
- active = Hash[active_versions]
282
- versions.each { |v| active[v].try(:store!, new_file) } unless active.empty?
283
- else
284
- active_versions.each { |name, v| v.store!(new_file) }
285
- end
314
+ def store_versions!(new_file)
315
+ versions_to_store.each { |name, v| v.store!(new_file) }
286
316
  end
287
317
 
288
318
  def remove_versions!
@@ -290,11 +320,11 @@ module CarrierWave
290
320
  end
291
321
 
292
322
  def retrieve_versions_from_cache!(cache_name)
293
- versions.each { |name, v| v.retrieve_from_cache!(cache_name) }
323
+ active_versions.each { |name, v| v.retrieve_from_cache!(cache_name) }
294
324
  end
295
325
 
296
326
  def retrieve_versions_from_store!(identifier)
297
- versions.each { |name, v| v.retrieve_from_store!(identifier) }
327
+ active_versions.each { |name, v| v.retrieve_from_store!(identifier) }
298
328
  end
299
329
 
300
330
  end # Versions
@@ -1,7 +1,4 @@
1
- # encoding: utf-8
2
-
3
1
  require 'carrierwave/utilities/uri'
4
- require 'carrierwave/utilities/deprecation'
5
2
 
6
3
  module CarrierWave
7
4
  module Utilities
@@ -1,16 +1,15 @@
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
+ SAFE_STRING = URI::REGEXP::PATTERN::UNRESERVED + '\/'
8
+ UNSAFE = Regexp.new("[^#{SAFE_STRING}]", false)
6
9
 
7
10
  private
8
11
  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)
12
-
13
- path.to_s.gsub(unsafe) do
12
+ path.to_s.gsub(UNSAFE) do
14
13
  us = $&
15
14
  tmp = ''
16
15
  us.each_byte do |uc|
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  require 'active_model/validator'
4
2
  require 'active_support/concern'
5
3
 
@@ -13,7 +11,7 @@ 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")
14
+ record.__send__("#{attribute}_processing_errors").each do |e|
17
15
  message = (e.message == e.class.to_s) ? :carrierwave_processing_error : e.message
18
16
  record.errors.add(attribute, message)
19
17
  end
@@ -23,7 +21,7 @@ module CarrierWave
23
21
  class IntegrityValidator < ::ActiveModel::EachValidator
24
22
 
25
23
  def validate_each(record, attribute, value)
26
- if e = record.send("#{attribute}_integrity_error")
24
+ record.__send__("#{attribute}_integrity_errors").each do |e|
27
25
  message = (e.message == e.class.to_s) ? :carrierwave_integrity_error : e.message
28
26
  record.errors.add(attribute, message)
29
27
  end
@@ -33,7 +31,7 @@ module CarrierWave
33
31
  class DownloadValidator < ::ActiveModel::EachValidator
34
32
 
35
33
  def validate_each(record, attribute, value)
36
- if e = record.send("#{attribute}_download_error")
34
+ record.__send__("#{attribute}_download_errors").each do |e|
37
35
  message = (e.message == e.class.to_s) ? :carrierwave_download_error : e.message
38
36
  record.errors.add(attribute, message)
39
37
  end