carrierwave 1.3.0 → 2.2.3
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 +120 -43
- data/lib/carrierwave/downloader/base.rb +93 -0
- data/lib/carrierwave/downloader/remote_file.rb +65 -0
- data/lib/carrierwave/locale/en.yml +5 -4
- data/lib/carrierwave/mount.rb +25 -19
- data/lib/carrierwave/mounter.rb +71 -48
- data/lib/carrierwave/orm/activerecord.rb +14 -8
- data/lib/carrierwave/processing/mini_magick.rb +100 -117
- data/lib/carrierwave/processing/rmagick.rb +11 -5
- data/lib/carrierwave/processing/vips.rb +284 -0
- data/lib/carrierwave/processing.rb +1 -0
- data/lib/carrierwave/sanitized_file.rb +44 -23
- data/lib/carrierwave/storage/file.rb +2 -2
- data/lib/carrierwave/storage/fog.rb +46 -17
- data/lib/carrierwave/storage.rb +1 -0
- data/lib/carrierwave/uploader/cache.rb +24 -16
- data/lib/carrierwave/uploader/configuration.rb +28 -15
- data/lib/carrierwave/uploader/content_type_blacklist.rb +17 -8
- data/lib/carrierwave/uploader/content_type_whitelist.rb +20 -8
- data/lib/carrierwave/uploader/download.rb +2 -80
- data/lib/carrierwave/uploader/extension_blacklist.rb +18 -10
- data/lib/carrierwave/uploader/extension_whitelist.rb +19 -10
- 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 +6 -3
- data/lib/carrierwave/uploader/versions.rb +43 -13
- data/lib/carrierwave/uploader.rb +0 -9
- data/lib/carrierwave/validations/active_model.rb +3 -3
- data/lib/carrierwave/version.rb +1 -1
- data/lib/carrierwave.rb +4 -0
- data/lib/generators/templates/uploader.rb +2 -2
- metadata +113 -21
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'carrierwave/downloader/base'
|
2
|
+
|
1
3
|
module CarrierWave
|
2
4
|
|
3
5
|
module Uploader
|
@@ -21,9 +23,10 @@ module CarrierWave
|
|
21
23
|
add_config :move_to_cache
|
22
24
|
add_config :move_to_store
|
23
25
|
add_config :remove_previously_stored_files_after_update
|
26
|
+
add_config :downloader
|
24
27
|
|
25
28
|
# fog
|
26
|
-
|
29
|
+
add_deprecated_config :fog_provider
|
27
30
|
add_config :fog_attributes
|
28
31
|
add_config :fog_credentials
|
29
32
|
add_config :fog_directory
|
@@ -107,8 +110,8 @@ module CarrierWave
|
|
107
110
|
# cache_storage CarrierWave::Storage::File
|
108
111
|
# cache_storage MyCustomStorageEngine
|
109
112
|
#
|
110
|
-
def cache_storage(storage =
|
111
|
-
|
113
|
+
def cache_storage(storage = false)
|
114
|
+
unless storage == false
|
112
115
|
self._cache_storage = storage.is_a?(Symbol) ? eval(storage_engines[storage]) : storage
|
113
116
|
end
|
114
117
|
_cache_storage
|
@@ -119,16 +122,8 @@ module CarrierWave
|
|
119
122
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
120
123
|
@#{name} = nil
|
121
124
|
|
122
|
-
def self.eager_load_fog(fog_credentials)
|
123
|
-
# see #1198. This will hopefully no longer be necessary after fog 2.0
|
124
|
-
require self.fog_provider
|
125
|
-
require 'carrierwave/storage/fog'
|
126
|
-
Fog::Storage.new(fog_credentials) if fog_credentials.present?
|
127
|
-
end unless defined? eager_load_fog
|
128
|
-
|
129
125
|
def self.#{name}(value=nil)
|
130
126
|
@#{name} = value if value
|
131
|
-
eager_load_fog(value) if value && '#{name}' == 'fog_credentials'
|
132
127
|
return @#{name} if self.object_id == #{self.object_id} || defined?(@#{name})
|
133
128
|
name = superclass.#{name}
|
134
129
|
return nil if name.nil? && !instance_variable_defined?(:@#{name})
|
@@ -136,12 +131,10 @@ module CarrierWave
|
|
136
131
|
end
|
137
132
|
|
138
133
|
def self.#{name}=(value)
|
139
|
-
eager_load_fog(value) if '#{name}' == 'fog_credentials' && value.present?
|
140
134
|
@#{name} = value
|
141
135
|
end
|
142
136
|
|
143
137
|
def #{name}=(value)
|
144
|
-
self.class.eager_load_fog(value) if '#{name}' == 'fog_credentials' && value.present?
|
145
138
|
@#{name} = value
|
146
139
|
end
|
147
140
|
|
@@ -157,6 +150,26 @@ module CarrierWave
|
|
157
150
|
RUBY
|
158
151
|
end
|
159
152
|
|
153
|
+
def add_deprecated_config(name)
|
154
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
155
|
+
def self.#{name}(value=nil)
|
156
|
+
ActiveSupport::Deprecation.warn "##{name} is deprecated and has no effect"
|
157
|
+
end
|
158
|
+
|
159
|
+
def self.#{name}=(value)
|
160
|
+
ActiveSupport::Deprecation.warn "##{name} is deprecated and has no effect"
|
161
|
+
end
|
162
|
+
|
163
|
+
def #{name}=(value)
|
164
|
+
ActiveSupport::Deprecation.warn "##{name} is deprecated and has no effect"
|
165
|
+
end
|
166
|
+
|
167
|
+
def #{name}
|
168
|
+
ActiveSupport::Deprecation.warn "##{name} is deprecated and has no effect"
|
169
|
+
end
|
170
|
+
RUBY
|
171
|
+
end
|
172
|
+
|
160
173
|
def configure
|
161
174
|
yield self
|
162
175
|
end
|
@@ -173,8 +186,7 @@ module CarrierWave
|
|
173
186
|
:fog => "CarrierWave::Storage::Fog"
|
174
187
|
}
|
175
188
|
config.storage = :file
|
176
|
-
config.cache_storage =
|
177
|
-
config.fog_provider = 'fog'
|
189
|
+
config.cache_storage = nil
|
178
190
|
config.fog_attributes = {}
|
179
191
|
config.fog_credentials = {}
|
180
192
|
config.fog_public = true
|
@@ -187,6 +199,7 @@ module CarrierWave
|
|
187
199
|
config.move_to_cache = false
|
188
200
|
config.move_to_store = false
|
189
201
|
config.remove_previously_stored_files_after_update = true
|
202
|
+
config.downloader = CarrierWave::Downloader::Base
|
190
203
|
config.ignore_integrity_errors = true
|
191
204
|
config.ignore_processing_errors = true
|
192
205
|
config.ignore_download_errors = true
|
@@ -8,39 +8,48 @@ module CarrierWave
|
|
8
8
|
end
|
9
9
|
|
10
10
|
##
|
11
|
-
# Override this method in your uploader to provide a
|
11
|
+
# Override this method in your uploader to provide a denylist of files content types
|
12
12
|
# which are not allowed to be uploaded.
|
13
13
|
# Not only strings but Regexp are allowed as well.
|
14
14
|
#
|
15
15
|
# === Returns
|
16
16
|
#
|
17
|
-
# [NilClass, String, Regexp, Array[String, Regexp]] a
|
17
|
+
# [NilClass, String, Regexp, Array[String, Regexp]] a denylist of content types which are not allowed to be uploaded
|
18
18
|
#
|
19
19
|
# === Examples
|
20
20
|
#
|
21
|
-
# def
|
21
|
+
# def content_type_denylist
|
22
22
|
# %w(text/json application/json)
|
23
23
|
# end
|
24
24
|
#
|
25
25
|
# Basically the same, but using a Regexp:
|
26
26
|
#
|
27
|
-
# def
|
27
|
+
# def content_type_denylist
|
28
28
|
# [/(text|application)\/json/]
|
29
29
|
# end
|
30
30
|
#
|
31
|
-
def
|
31
|
+
def content_type_denylist
|
32
|
+
if respond_to?(:content_type_blacklist)
|
33
|
+
ActiveSupport::Deprecation.warn "#content_type_blacklist is deprecated, use #content_type_denylist instead." unless instance_variable_defined?(:@content_type_blacklist_warned)
|
34
|
+
@content_type_blacklist_warned = true
|
35
|
+
content_type_blacklist
|
36
|
+
end
|
37
|
+
end
|
32
38
|
|
33
39
|
private
|
34
40
|
|
35
41
|
def check_content_type_blacklist!(new_file)
|
42
|
+
return unless content_type_denylist
|
43
|
+
|
36
44
|
content_type = new_file.content_type
|
37
|
-
if
|
38
|
-
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.content_type_blacklist_error",
|
45
|
+
if blacklisted_content_type?(content_type)
|
46
|
+
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.content_type_blacklist_error",
|
47
|
+
content_type: content_type, default: :"errors.messages.content_type_denylist_error")
|
39
48
|
end
|
40
49
|
end
|
41
50
|
|
42
51
|
def blacklisted_content_type?(content_type)
|
43
|
-
Array(
|
52
|
+
Array(content_type_denylist).any? { |item| content_type =~ /#{item}/ }
|
44
53
|
end
|
45
54
|
|
46
55
|
end # ContentTypeBlacklist
|
@@ -8,39 +8,51 @@ module CarrierWave
|
|
8
8
|
end
|
9
9
|
|
10
10
|
##
|
11
|
-
# Override this method in your uploader to provide
|
11
|
+
# Override this method in your uploader to provide an allowlist of files content types
|
12
12
|
# which are allowed to be uploaded.
|
13
13
|
# Not only strings but Regexp are allowed as well.
|
14
14
|
#
|
15
15
|
# === Returns
|
16
16
|
#
|
17
|
-
# [NilClass, String, Regexp, Array[String, Regexp]]
|
17
|
+
# [NilClass, String, Regexp, Array[String, Regexp]] an allowlist of content types which are allowed to be uploaded
|
18
18
|
#
|
19
19
|
# === Examples
|
20
20
|
#
|
21
|
-
# def
|
21
|
+
# def content_type_allowlist
|
22
22
|
# %w(text/json application/json)
|
23
23
|
# end
|
24
24
|
#
|
25
25
|
# Basically the same, but using a Regexp:
|
26
26
|
#
|
27
|
-
# def
|
27
|
+
# def content_type_allowlist
|
28
28
|
# [/(text|application)\/json/]
|
29
29
|
# end
|
30
30
|
#
|
31
|
-
def
|
31
|
+
def content_type_allowlist
|
32
|
+
if respond_to?(:content_type_whitelist)
|
33
|
+
ActiveSupport::Deprecation.warn "#content_type_whitelist is deprecated, use #content_type_allowlist instead." unless instance_variable_defined?(:@content_type_whitelist_warned)
|
34
|
+
@content_type_whitelist_warned = true
|
35
|
+
content_type_whitelist
|
36
|
+
end
|
37
|
+
end
|
32
38
|
|
33
39
|
private
|
34
40
|
|
35
41
|
def check_content_type_whitelist!(new_file)
|
42
|
+
return unless content_type_allowlist
|
43
|
+
|
36
44
|
content_type = new_file.content_type
|
37
|
-
if
|
38
|
-
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.content_type_whitelist_error", content_type: content_type,
|
45
|
+
if !whitelisted_content_type?(content_type)
|
46
|
+
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.content_type_whitelist_error", content_type: content_type,
|
47
|
+
allowed_types: Array(content_type_allowlist).join(", "), default: :"errors.messages.content_type_allowlist_error")
|
39
48
|
end
|
40
49
|
end
|
41
50
|
|
42
51
|
def whitelisted_content_type?(content_type)
|
43
|
-
Array(
|
52
|
+
Array(content_type_allowlist).any? do |item|
|
53
|
+
item = Regexp.quote(item) if item.class != Regexp
|
54
|
+
content_type =~ /#{item}/
|
55
|
+
end
|
44
56
|
end
|
45
57
|
|
46
58
|
end # ContentTypeWhitelist
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'open-uri'
|
2
|
-
|
3
1
|
module CarrierWave
|
4
2
|
module Uploader
|
5
3
|
module Download
|
@@ -9,64 +7,8 @@ module CarrierWave
|
|
9
7
|
include CarrierWave::Uploader::Configuration
|
10
8
|
include CarrierWave::Uploader::Cache
|
11
9
|
|
12
|
-
class RemoteFile
|
13
|
-
def initialize(uri, remote_headers = {})
|
14
|
-
@uri = uri
|
15
|
-
@remote_headers = remote_headers
|
16
|
-
@file = nil
|
17
|
-
end
|
18
|
-
|
19
|
-
def original_filename
|
20
|
-
filename = filename_from_header || filename_from_uri
|
21
|
-
mime_type = MIME::Types[file.content_type].first
|
22
|
-
unless File.extname(filename).present? || mime_type.blank?
|
23
|
-
filename = "#{filename}.#{mime_type.extensions.first}"
|
24
|
-
end
|
25
|
-
filename
|
26
|
-
end
|
27
|
-
|
28
|
-
def respond_to?(*args)
|
29
|
-
super or file.respond_to?(*args)
|
30
|
-
end
|
31
|
-
|
32
|
-
def http?
|
33
|
-
@uri.scheme =~ /^https?$/
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
def file
|
39
|
-
if @file.blank?
|
40
|
-
headers = @remote_headers.
|
41
|
-
reverse_merge('User-Agent' => "CarrierWave/#{CarrierWave::VERSION}")
|
42
|
-
|
43
|
-
@file = Kernel.open(@uri.to_s, headers)
|
44
|
-
@file = @file.is_a?(String) ? StringIO.new(@file) : @file
|
45
|
-
end
|
46
|
-
@file
|
47
|
-
|
48
|
-
rescue StandardError => e
|
49
|
-
raise CarrierWave::DownloadError, "could not download file: #{e.message}"
|
50
|
-
end
|
51
|
-
|
52
|
-
def filename_from_header
|
53
|
-
if file.meta.include? 'content-disposition'
|
54
|
-
match = file.meta['content-disposition'].match(/filename="?([^"]+)/)
|
55
|
-
return match[1] unless match.nil? || match[1].empty?
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def filename_from_uri
|
60
|
-
URI.decode(File.basename(file.base_uri.path))
|
61
|
-
end
|
62
|
-
|
63
|
-
def method_missing(*args, &block)
|
64
|
-
file.send(*args, &block)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
10
|
##
|
69
|
-
# Caches the file by downloading it from the given URL.
|
11
|
+
# Caches the file by downloading it from the given URL, using downloader.
|
70
12
|
#
|
71
13
|
# === Parameters
|
72
14
|
#
|
@@ -74,29 +16,9 @@ module CarrierWave
|
|
74
16
|
# [remote_headers (Hash)] Request headers
|
75
17
|
#
|
76
18
|
def download!(uri, remote_headers = {})
|
77
|
-
|
78
|
-
file = RemoteFile.new(processed_uri, remote_headers)
|
79
|
-
raise CarrierWave::DownloadError, "trying to download a file which is not served over HTTP" unless file.http?
|
19
|
+
file = downloader.new(self).download(uri, remote_headers)
|
80
20
|
cache!(file)
|
81
21
|
end
|
82
|
-
|
83
|
-
##
|
84
|
-
# Processes the given URL by parsing and escaping it. Public to allow overriding.
|
85
|
-
#
|
86
|
-
# === Parameters
|
87
|
-
#
|
88
|
-
# [url (String)] The URL where the remote file is stored
|
89
|
-
#
|
90
|
-
def process_uri(uri)
|
91
|
-
URI.parse(uri)
|
92
|
-
rescue URI::InvalidURIError
|
93
|
-
uri_parts = uri.split('?')
|
94
|
-
# regexp from Ruby's URI::Parser#regexp[:UNSAFE], with [] specifically removed
|
95
|
-
encoded_uri = URI.encode(uri_parts.shift, /[^\-_.!~*'()a-zA-Z\d;\/?:@&=+$,]/)
|
96
|
-
encoded_uri << '?' << URI.encode(uri_parts.join('?')) if uri_parts.any?
|
97
|
-
URI.parse(encoded_uri) rescue raise CarrierWave::DownloadError, "couldn't parse URL"
|
98
|
-
end
|
99
|
-
|
100
22
|
end # Download
|
101
23
|
end # Uploader
|
102
24
|
end # CarrierWave
|
@@ -8,43 +8,51 @@ module CarrierWave
|
|
8
8
|
end
|
9
9
|
|
10
10
|
##
|
11
|
-
# Override this method in your uploader to provide a
|
11
|
+
# Override this method in your uploader to provide a denylist of extensions which
|
12
12
|
# are prohibited to be uploaded. Compares the file's extension case insensitive.
|
13
13
|
# Furthermore, not only strings but Regexp are allowed as well.
|
14
14
|
#
|
15
|
-
# When using a Regexp in the
|
15
|
+
# When using a Regexp in the denylist, `\A` and `\z` are automatically added to
|
16
16
|
# the Regexp expression, also case insensitive.
|
17
17
|
#
|
18
18
|
# === Returns
|
19
19
|
|
20
|
-
# [NilClass, String, Regexp, Array[String, Regexp]] a
|
20
|
+
# [NilClass, String, Regexp, Array[String, Regexp]] a deny list of extensions which are prohibited to be uploaded
|
21
21
|
#
|
22
22
|
# === Examples
|
23
23
|
#
|
24
|
-
# def
|
24
|
+
# def extension_denylist
|
25
25
|
# %w(swf tiff)
|
26
26
|
# end
|
27
27
|
#
|
28
28
|
# Basically the same, but using a Regexp:
|
29
29
|
#
|
30
|
-
# def
|
30
|
+
# def extension_denylist
|
31
31
|
# [/swf/, 'tiff']
|
32
32
|
# end
|
33
33
|
#
|
34
|
-
|
35
|
-
|
34
|
+
def extension_denylist
|
35
|
+
if respond_to?(:extension_blacklist)
|
36
|
+
ActiveSupport::Deprecation.warn "#extension_blacklist is deprecated, use #extension_denylist instead." unless instance_variable_defined?(:@extension_blacklist_warned)
|
37
|
+
@extension_blacklist_warned = true
|
38
|
+
extension_blacklist
|
39
|
+
end
|
40
|
+
end
|
36
41
|
|
37
42
|
private
|
38
43
|
|
39
44
|
def check_extension_blacklist!(new_file)
|
45
|
+
return unless extension_denylist
|
46
|
+
|
40
47
|
extension = new_file.extension.to_s
|
41
|
-
if
|
42
|
-
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.extension_blacklist_error", extension: new_file.extension.inspect,
|
48
|
+
if blacklisted_extension?(extension)
|
49
|
+
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.extension_blacklist_error", extension: new_file.extension.inspect,
|
50
|
+
prohibited_types: Array(extension_denylist).join(", "), default: :"errors.messages.extension_denylist_error")
|
43
51
|
end
|
44
52
|
end
|
45
53
|
|
46
54
|
def blacklisted_extension?(extension)
|
47
|
-
Array(
|
55
|
+
Array(extension_denylist).any? { |item| extension =~ /\A#{item}\z/i }
|
48
56
|
end
|
49
57
|
end
|
50
58
|
end
|
@@ -8,45 +8,54 @@ module CarrierWave
|
|
8
8
|
end
|
9
9
|
|
10
10
|
##
|
11
|
-
# Override this method in your uploader to provide
|
11
|
+
# Override this method in your uploader to provide an allowlist of extensions which
|
12
12
|
# are allowed to be uploaded. Compares the file's extension case insensitive.
|
13
13
|
# Furthermore, not only strings but Regexp are allowed as well.
|
14
14
|
#
|
15
|
-
# When using a Regexp in the
|
15
|
+
# When using a Regexp in the allowlist, `\A` and `\z` are automatically added to
|
16
16
|
# the Regexp expression, also case insensitive.
|
17
17
|
#
|
18
18
|
# === Returns
|
19
19
|
#
|
20
|
-
# [NilClass, String, Regexp, Array[String, Regexp]]
|
20
|
+
# [NilClass, String, Regexp, Array[String, Regexp]] an allowlist of extensions which are allowed to be uploaded
|
21
21
|
#
|
22
22
|
# === Examples
|
23
23
|
#
|
24
|
-
# def
|
24
|
+
# def extension_allowlist
|
25
25
|
# %w(jpg jpeg gif png)
|
26
26
|
# end
|
27
27
|
#
|
28
28
|
# Basically the same, but using a Regexp:
|
29
29
|
#
|
30
|
-
# def
|
30
|
+
# def extension_allowlist
|
31
31
|
# [/jpe?g/, 'gif', 'png']
|
32
32
|
# end
|
33
33
|
#
|
34
|
-
def
|
34
|
+
def extension_allowlist
|
35
|
+
if respond_to?(:extension_whitelist)
|
36
|
+
ActiveSupport::Deprecation.warn "#extension_whitelist is deprecated, use #extension_allowlist instead." unless instance_variable_defined?(:@extension_whitelist_warned)
|
37
|
+
@extension_whitelist_warned = true
|
38
|
+
extension_whitelist
|
39
|
+
end
|
40
|
+
end
|
35
41
|
|
36
42
|
private
|
37
43
|
|
38
44
|
def check_extension_whitelist!(new_file)
|
45
|
+
return unless extension_allowlist
|
46
|
+
|
39
47
|
extension = new_file.extension.to_s
|
40
|
-
if
|
41
|
-
|
48
|
+
if !whitelisted_extension?(extension)
|
49
|
+
# Look for whitelist first, then fallback to allowlist
|
50
|
+
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.extension_whitelist_error", extension: new_file.extension.inspect,
|
51
|
+
allowed_types: Array(extension_allowlist).join(", "), default: :"errors.messages.extension_allowlist_error")
|
42
52
|
end
|
43
53
|
end
|
44
54
|
|
45
55
|
def whitelisted_extension?(extension)
|
46
56
|
downcase_extension = extension.downcase
|
47
|
-
Array(
|
57
|
+
Array(extension_allowlist).any? { |item| downcase_extension =~ /\A#{item}\z/i }
|
48
58
|
end
|
49
|
-
|
50
59
|
end # ExtensionWhitelist
|
51
60
|
end # Uploader
|
52
61
|
end # CarrierWave
|
@@ -33,6 +33,12 @@ module CarrierWave
|
|
33
33
|
@mounted_as = mounted_as
|
34
34
|
end
|
35
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
|
36
42
|
end # Mountable
|
37
43
|
end # Uploader
|
38
44
|
end # CarrierWave
|
@@ -23,14 +23,14 @@ module CarrierWave
|
|
23
23
|
alias_method :path, :current_path
|
24
24
|
|
25
25
|
##
|
26
|
-
# Returns a string that uniquely identifies the last stored file
|
26
|
+
# Returns a string that uniquely identifies the retrieved or last stored file
|
27
27
|
#
|
28
28
|
# === Returns
|
29
29
|
#
|
30
30
|
# [String] uniquely identifies a file
|
31
31
|
#
|
32
32
|
def identifier
|
33
|
-
storage.try(:identifier)
|
33
|
+
@identifier || storage.try(:identifier)
|
34
34
|
end
|
35
35
|
|
36
36
|
##
|
@@ -7,7 +7,7 @@ module CarrierWave
|
|
7
7
|
extend ActiveSupport::Concern
|
8
8
|
|
9
9
|
def serializable_hash(options = nil)
|
10
|
-
{"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 }] }]
|
11
11
|
end
|
12
12
|
|
13
13
|
def as_json(options=nil)
|
@@ -11,7 +11,7 @@ module CarrierWave
|
|
11
11
|
prepend Module.new {
|
12
12
|
def initialize(*)
|
13
13
|
super
|
14
|
-
@file, @filename, @cache_id = nil
|
14
|
+
@file, @filename, @cache_id, @identifier = nil
|
15
15
|
end
|
16
16
|
}
|
17
17
|
end
|
@@ -61,7 +61,7 @@ module CarrierWave
|
|
61
61
|
#
|
62
62
|
def store!(new_file=nil)
|
63
63
|
cache!(new_file) if new_file && ((@cache_id != parent_cache_id) || @cache_id.nil?)
|
64
|
-
if !cache_only
|
64
|
+
if !cache_only && @file && @cache_id
|
65
65
|
with_callbacks(:store, new_file) do
|
66
66
|
new_file = storage.store!(@file)
|
67
67
|
if delete_tmp_file_after_storage
|
@@ -69,7 +69,8 @@ module CarrierWave
|
|
69
69
|
cache_storage.delete_dir!(cache_path(nil))
|
70
70
|
end
|
71
71
|
@file = new_file
|
72
|
-
@cache_id = nil
|
72
|
+
@cache_id = @identifier = nil
|
73
|
+
@staged = false
|
73
74
|
end
|
74
75
|
end
|
75
76
|
end
|
@@ -84,6 +85,7 @@ module CarrierWave
|
|
84
85
|
def retrieve_from_store!(identifier)
|
85
86
|
with_callbacks(:retrieve_from_store, identifier) do
|
86
87
|
@file = storage.retrieve!(identifier)
|
88
|
+
@identifier = identifier
|
87
89
|
end
|
88
90
|
end
|
89
91
|
|
@@ -15,9 +15,12 @@ module CarrierWave
|
|
15
15
|
# [String] the location where this file is accessible via a url
|
16
16
|
#
|
17
17
|
def url(options = {})
|
18
|
-
if file.respond_to?(:url)
|
19
|
-
file.method(:url).arity
|
20
|
-
|
18
|
+
if file.respond_to?(:url)
|
19
|
+
tmp_url = file.method(:url).arity.zero? ? file.url : file.url(options)
|
20
|
+
return tmp_url if tmp_url.present?
|
21
|
+
end
|
22
|
+
|
23
|
+
if file.respond_to?(:path)
|
21
24
|
path = encode_path(file.path.sub(File.expand_path(root), ''))
|
22
25
|
|
23
26
|
if host = asset_host
|
@@ -23,7 +23,7 @@ module CarrierWave
|
|
23
23
|
prepend Module.new {
|
24
24
|
def initialize(*)
|
25
25
|
super
|
26
|
-
@versions = nil
|
26
|
+
@versions, @versions_to_cache, @versions_to_store = nil
|
27
27
|
end
|
28
28
|
}
|
29
29
|
end
|
@@ -220,16 +220,18 @@ module CarrierWave
|
|
220
220
|
# Recreate versions and reprocess them. This can be used to recreate
|
221
221
|
# versions if their parameters somehow have changed.
|
222
222
|
#
|
223
|
-
def recreate_versions!(*
|
223
|
+
def recreate_versions!(*names)
|
224
224
|
# Some files could possibly not be stored on the local disk. This
|
225
225
|
# doesn't play nicely with processing. Make sure that we're only
|
226
226
|
# processing a cached file
|
227
227
|
#
|
228
228
|
# The call to store! will trigger the necessary callbacks to both
|
229
229
|
# process this version and all sub-versions
|
230
|
-
|
231
|
-
|
232
|
-
|
230
|
+
|
231
|
+
if names.any?
|
232
|
+
set_versions_to_cache_and_store(names)
|
233
|
+
store!(file)
|
234
|
+
reset_versions_to_cache_and_store
|
233
235
|
else
|
234
236
|
cache! if !cached?
|
235
237
|
store!
|
@@ -237,6 +239,39 @@ module CarrierWave
|
|
237
239
|
end
|
238
240
|
|
239
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
|
+
|
240
275
|
def assign_parent_cache_id(file)
|
241
276
|
active_versions.each do |name, uploader|
|
242
277
|
uploader.parent_cache_id = @cache_id
|
@@ -270,19 +305,14 @@ module CarrierWave
|
|
270
305
|
end
|
271
306
|
|
272
307
|
def cache_versions!(new_file)
|
273
|
-
|
308
|
+
versions_to_cache.each do |name, v|
|
274
309
|
v.send(:cache_id=, @cache_id)
|
275
310
|
v.cache!(new_file)
|
276
311
|
end
|
277
312
|
end
|
278
313
|
|
279
|
-
def store_versions!(new_file
|
280
|
-
|
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!
|
data/lib/carrierwave/uploader.rb
CHANGED
@@ -43,15 +43,6 @@ module CarrierWave
|
|
43
43
|
class Base
|
44
44
|
attr_reader :file
|
45
45
|
|
46
|
-
##
|
47
|
-
# Workaround for class_attribute malfunction when used with Module#prepend
|
48
|
-
#
|
49
|
-
if RUBY_VERSION < '2.1.0'
|
50
|
-
def self.singleton_class?
|
51
|
-
!ancestors.include? self
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
46
|
include CarrierWave::Uploader::Configuration
|
56
47
|
include CarrierWave::Uploader::Callbacks
|
57
48
|
include CarrierWave::Uploader::Proxy
|