carrierwave 0.10.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.

Files changed (61) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +307 -121
  3. data/lib/carrierwave/compatibility/paperclip.rb +0 -2
  4. data/lib/carrierwave/downloader/base.rb +83 -0
  5. data/lib/carrierwave/downloader/remote_file.rb +65 -0
  6. data/lib/carrierwave/error.rb +1 -0
  7. data/lib/carrierwave/locale/en.yml +7 -4
  8. data/lib/carrierwave/mount.rb +229 -180
  9. data/lib/carrierwave/mounter.rb +188 -0
  10. data/lib/carrierwave/orm/activerecord.rb +59 -24
  11. data/lib/carrierwave/processing/mini_magick.rb +137 -83
  12. data/lib/carrierwave/processing/rmagick.rb +65 -8
  13. data/lib/carrierwave/processing.rb +0 -1
  14. data/lib/carrierwave/sanitized_file.rb +67 -32
  15. data/lib/carrierwave/storage/abstract.rb +15 -2
  16. data/lib/carrierwave/storage/file.rb +69 -2
  17. data/lib/carrierwave/storage/fog.rb +177 -39
  18. data/lib/carrierwave/storage.rb +1 -7
  19. data/lib/carrierwave/test/matchers.rb +77 -12
  20. data/lib/carrierwave/uploader/cache.rb +74 -38
  21. data/lib/carrierwave/uploader/callbacks.rb +0 -2
  22. data/lib/carrierwave/uploader/configuration.rb +71 -13
  23. data/lib/carrierwave/uploader/content_type_blacklist.rb +48 -0
  24. data/lib/carrierwave/uploader/content_type_whitelist.rb +48 -0
  25. data/lib/carrierwave/uploader/default_url.rb +3 -5
  26. data/lib/carrierwave/uploader/download.rb +4 -74
  27. data/lib/carrierwave/uploader/extension_blacklist.rb +14 -10
  28. data/lib/carrierwave/uploader/extension_whitelist.rb +13 -10
  29. data/lib/carrierwave/uploader/file_size.rb +43 -0
  30. data/lib/carrierwave/uploader/mountable.rb +13 -8
  31. data/lib/carrierwave/uploader/processing.rb +10 -10
  32. data/lib/carrierwave/uploader/proxy.rb +6 -8
  33. data/lib/carrierwave/uploader/remove.rb +0 -2
  34. data/lib/carrierwave/uploader/serialization.rb +2 -4
  35. data/lib/carrierwave/uploader/store.rb +17 -24
  36. data/lib/carrierwave/uploader/url.rb +3 -5
  37. data/lib/carrierwave/uploader/versions.rb +123 -93
  38. data/lib/carrierwave/uploader.rb +6 -2
  39. data/lib/carrierwave/utilities/uri.rb +5 -6
  40. data/lib/carrierwave/utilities.rb +0 -3
  41. data/lib/carrierwave/validations/active_model.rb +3 -5
  42. data/lib/carrierwave/version.rb +1 -1
  43. data/lib/carrierwave.rb +34 -8
  44. data/lib/generators/templates/uploader.rb +4 -8
  45. metadata +130 -57
  46. data/lib/carrierwave/locale/cs.yml +0 -11
  47. data/lib/carrierwave/locale/de.yml +0 -11
  48. data/lib/carrierwave/locale/el.yml +0 -11
  49. data/lib/carrierwave/locale/es.yml +0 -11
  50. data/lib/carrierwave/locale/fr.yml +0 -11
  51. data/lib/carrierwave/locale/ja.yml +0 -11
  52. data/lib/carrierwave/locale/nb.yml +0 -11
  53. data/lib/carrierwave/locale/nl.yml +0 -11
  54. data/lib/carrierwave/locale/pl.yml +0 -11
  55. data/lib/carrierwave/locale/pt-BR.yml +0 -11
  56. data/lib/carrierwave/locale/pt-PT.yml +0 -11
  57. data/lib/carrierwave/locale/ru.yml +0 -11
  58. data/lib/carrierwave/locale/sk.yml +0 -11
  59. data/lib/carrierwave/locale/tr.yml +0 -11
  60. data/lib/carrierwave/processing/mime_types.rb +0 -74
  61. data/lib/carrierwave/utilities/deprecation.rb +0 -18
@@ -1,12 +1,10 @@
1
- # encoding: utf-8
2
-
3
1
  module CarrierWave
4
2
  module Uploader
5
3
  module ExtensionWhitelist
6
4
  extend ActiveSupport::Concern
7
5
 
8
6
  included do
9
- before :cache, :check_whitelist!
7
+ before :cache, :check_extension_whitelist!
10
8
  end
11
9
 
12
10
  ##
@@ -19,31 +17,36 @@ module CarrierWave
19
17
  #
20
18
  # === Returns
21
19
  #
22
- # [NilClass, Array[String,Regexp]] a white list of extensions which are allowed to be uploaded
20
+ # [NilClass, String, Regexp, Array[String, Regexp]] a white list of extensions which are allowed to be uploaded
23
21
  #
24
22
  # === Examples
25
23
  #
26
- # def extension_white_list
24
+ # def extension_whitelist
27
25
  # %w(jpg jpeg gif png)
28
26
  # end
29
27
  #
30
28
  # Basically the same, but using a Regexp:
31
29
  #
32
- # def extension_white_list
30
+ # def extension_whitelist
33
31
  # [/jpe?g/, 'gif', 'png']
34
32
  # end
35
33
  #
36
- def extension_white_list; end
34
+ def extension_whitelist; end
37
35
 
38
36
  private
39
37
 
40
- def check_whitelist!(new_file)
38
+ def check_extension_whitelist!(new_file)
41
39
  extension = new_file.extension.to_s
42
- if extension_white_list and not extension_white_list.detect { |item| extension =~ /\A#{item}\z/i }
43
- raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.extension_white_list_error", :extension => new_file.extension.inspect, :allowed_types => extension_white_list.join(", "))
40
+ if extension_whitelist && !whitelisted_extension?(extension)
41
+ raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.extension_whitelist_error", extension: new_file.extension.inspect, allowed_types: Array(extension_whitelist).join(", "))
44
42
  end
45
43
  end
46
44
 
45
+ def whitelisted_extension?(extension)
46
+ downcase_extension = extension.downcase
47
+ Array(extension_whitelist).any? { |item| downcase_extension =~ /\A#{item}\z/i }
48
+ end
49
+
47
50
  end # ExtensionWhitelist
48
51
  end # Uploader
49
52
  end # CarrierWave
@@ -0,0 +1,43 @@
1
+ require 'active_support'
2
+
3
+ module CarrierWave
4
+ module Uploader
5
+ module FileSize
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ before :cache, :check_size!
10
+ end
11
+
12
+ ##
13
+ # Override this method in your uploader to provide a Range of Size which
14
+ # are allowed to be uploaded.
15
+ # === Returns
16
+ #
17
+ # [NilClass, Range] a size range which are permitted to be uploaded
18
+ #
19
+ # === Examples
20
+ #
21
+ # def size_range
22
+ # 3256...5748
23
+ # end
24
+ #
25
+ def size_range; end
26
+
27
+ private
28
+
29
+ def check_size!(new_file)
30
+ size = new_file.size
31
+ expected_size_range = size_range
32
+ if expected_size_range.is_a?(::Range)
33
+ if size < expected_size_range.min
34
+ raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.min_size_error", :min_size => ActiveSupport::NumberHelper.number_to_human_size(expected_size_range.min))
35
+ elsif size > expected_size_range.max
36
+ raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.max_size_error", :max_size => ActiveSupport::NumberHelper.number_to_human_size(expected_size_range.max))
37
+ end
38
+ end
39
+ end
40
+
41
+ end # FileSize
42
+ end # Uploader
43
+ end # CarrierWave
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module CarrierWave
4
2
  module Uploader
5
3
  module Mountable
@@ -7,13 +5,14 @@ module CarrierWave
7
5
  attr_reader :model, :mounted_as
8
6
 
9
7
  ##
10
- # If a model is given as the first parameter, it will be stored in the uploader, and
11
- # available throught +#model+. Likewise, mounted_as stores the name of the column
12
- # where this instance of the uploader is mounted. These values can then be used inside
13
- # your uploader.
8
+ # If a model is given as the first parameter, it will be stored in the
9
+ # uploader, and available through +#model+. Likewise, mounted_as stores
10
+ # the name of the column where this instance of the uploader is mounted.
11
+ # These values can then be used inside your uploader.
14
12
  #
15
- # If you do not wish to mount your uploaders with the ORM extensions in -more then you
16
- # can override this method inside your uploader. Just be sure to call +super+
13
+ # If you do not wish to mount your uploaders with the ORM extensions in
14
+ # -more then you can override this method inside your uploader. Just be
15
+ # sure to call +super+
17
16
  #
18
17
  # === Parameters
19
18
  #
@@ -34,6 +33,12 @@ module CarrierWave
34
33
  @mounted_as = mounted_as
35
34
  end
36
35
 
36
+ ##
37
+ # Returns array index of given uploader within currently mounted uploaders
38
+ #
39
+ def index
40
+ model.__send__(:_mounter, mounted_as).uploaders.index(self)
41
+ end
37
42
  end # Mountable
38
43
  end # Uploader
39
44
  end # CarrierWave
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module CarrierWave
4
2
  module Uploader
5
3
  module Processing
@@ -11,7 +9,7 @@ module CarrierWave
11
9
  class_attribute :processors, :instance_writer => false
12
10
  self.processors = []
13
11
 
14
- after :cache, :process!
12
+ before :cache, :process!
15
13
  end
16
14
 
17
15
  module ClassMethods
@@ -73,15 +71,17 @@ module CarrierWave
73
71
  def process!(new_file=nil)
74
72
  return unless enable_processing
75
73
 
76
- self.class.processors.each do |method, args, condition|
77
- if(condition)
78
- if condition.respond_to?(:call)
79
- next unless condition.call(self, :args => args, :method => method, :file => new_file)
80
- else
81
- next unless self.send(condition, new_file)
74
+ with_callbacks(:process, new_file) do
75
+ self.class.processors.each do |method, args, condition|
76
+ if(condition)
77
+ if condition.respond_to?(:call)
78
+ next unless condition.call(self, :args => args, :method => method, :file => new_file)
79
+ else
80
+ next unless self.send(condition, new_file)
81
+ end
82
82
  end
83
+ self.send(method, *args)
83
84
  end
84
- self.send(method, *args)
85
85
  end
86
86
  end
87
87
 
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module CarrierWave
4
2
  module Uploader
5
3
  module Proxy
@@ -19,20 +17,20 @@ module CarrierWave
19
17
  # [String] the path where the file is currently located.
20
18
  #
21
19
  def current_path
22
- file.path if file.respond_to?(:path)
20
+ file.try(:path)
23
21
  end
24
22
 
25
23
  alias_method :path, :current_path
26
24
 
27
25
  ##
28
- # Returns a string that uniquely identifies the last stored file
26
+ # Returns a string that uniquely identifies the retrieved or last stored file
29
27
  #
30
28
  # === Returns
31
29
  #
32
30
  # [String] uniquely identifies a file
33
31
  #
34
32
  def identifier
35
- storage.identifier if storage.respond_to?(:identifier)
33
+ @identifier || storage.try(:identifier)
36
34
  end
37
35
 
38
36
  ##
@@ -43,7 +41,7 @@ module CarrierWave
43
41
  # [String] contents of the file
44
42
  #
45
43
  def read
46
- file.read if file.respond_to?(:read)
44
+ file.try(:read)
47
45
  end
48
46
 
49
47
  ##
@@ -54,7 +52,7 @@ module CarrierWave
54
52
  # [Integer] size of the file
55
53
  #
56
54
  def size
57
- file.respond_to?(:size) ? file.size : 0
55
+ file.try(:size) || 0
58
56
  end
59
57
 
60
58
  ##
@@ -80,7 +78,7 @@ module CarrierWave
80
78
  # [String] content type of the file
81
79
  #
82
80
  def content_type
83
- file.respond_to?(:content_type) ? file.content_type : nil
81
+ file.try(:content_type)
84
82
  end
85
83
 
86
84
  end # Proxy
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module CarrierWave
4
2
  module Uploader
5
3
  module Remove
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  require "json"
4
2
  require "active_support/core_ext/hash"
5
3
 
@@ -9,11 +7,11 @@ module CarrierWave
9
7
  extend ActiveSupport::Concern
10
8
 
11
9
  def serializable_hash(options = nil)
12
- {"url" => url}.merge Hash[versions.map { |name, version| [name, { "url" => version.url }] }]
10
+ {"url" => url}.merge Hash[versions.map { |name, version| [name.to_s, { "url" => version.url }] }]
13
11
  end
14
12
 
15
13
  def as_json(options=nil)
16
- Hash[mounted_as || "uploader", serializable_hash]
14
+ serializable_hash
17
15
  end
18
16
 
19
17
  def to_json(options=nil)
@@ -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