carrierwave 0.11.2 → 3.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/README.md +495 -173
- data/lib/carrierwave/compatibility/paperclip.rb +4 -4
- data/lib/carrierwave/downloader/base.rb +101 -0
- data/lib/carrierwave/downloader/remote_file.rb +68 -0
- data/lib/carrierwave/error.rb +1 -0
- data/lib/carrierwave/locale/en.yml +11 -5
- data/lib/carrierwave/mount.rb +217 -182
- data/lib/carrierwave/mounter.rb +257 -0
- data/lib/carrierwave/orm/activerecord.rb +29 -35
- data/lib/carrierwave/processing/mini_magick.rb +169 -84
- data/lib/carrierwave/processing/rmagick.rb +107 -25
- data/lib/carrierwave/processing/vips.rb +315 -0
- data/lib/carrierwave/processing.rb +1 -1
- data/lib/carrierwave/sanitized_file.rb +105 -87
- data/lib/carrierwave/storage/abstract.rb +16 -3
- data/lib/carrierwave/storage/file.rb +71 -3
- data/lib/carrierwave/storage/fog.rb +228 -57
- data/lib/carrierwave/storage.rb +1 -9
- data/lib/carrierwave/test/matchers.rb +88 -19
- data/lib/carrierwave/uploader/cache.rb +75 -45
- data/lib/carrierwave/uploader/callbacks.rb +1 -3
- data/lib/carrierwave/uploader/configuration.rb +84 -16
- data/lib/carrierwave/uploader/content_type_allowlist.rb +62 -0
- data/lib/carrierwave/uploader/content_type_denylist.rb +62 -0
- data/lib/carrierwave/uploader/default_url.rb +3 -5
- data/lib/carrierwave/uploader/dimension.rb +66 -0
- data/lib/carrierwave/uploader/download.rb +4 -74
- data/lib/carrierwave/uploader/extension_allowlist.rb +63 -0
- data/lib/carrierwave/uploader/extension_denylist.rb +64 -0
- data/lib/carrierwave/uploader/file_size.rb +43 -0
- data/lib/carrierwave/uploader/mountable.rb +13 -8
- data/lib/carrierwave/uploader/processing.rb +51 -13
- data/lib/carrierwave/uploader/proxy.rb +20 -9
- data/lib/carrierwave/uploader/remove.rb +0 -2
- data/lib/carrierwave/uploader/serialization.rb +2 -4
- data/lib/carrierwave/uploader/store.rb +85 -28
- data/lib/carrierwave/uploader/url.rb +8 -7
- data/lib/carrierwave/uploader/versions.rb +175 -125
- data/lib/carrierwave/uploader.rb +12 -10
- data/lib/carrierwave/utilities/file_name.rb +47 -0
- data/lib/carrierwave/utilities/uri.rb +14 -12
- data/lib/carrierwave/utilities.rb +1 -3
- data/lib/carrierwave/validations/active_model.rb +7 -11
- data/lib/carrierwave/version.rb +1 -1
- data/lib/carrierwave.rb +48 -21
- data/lib/generators/templates/{uploader.rb → uploader.rb.erb} +8 -11
- data/lib/generators/uploader_generator.rb +3 -3
- metadata +124 -86
- data/lib/carrierwave/locale/cs.yml +0 -11
- data/lib/carrierwave/locale/de.yml +0 -11
- data/lib/carrierwave/locale/el.yml +0 -11
- data/lib/carrierwave/locale/es.yml +0 -11
- data/lib/carrierwave/locale/fr.yml +0 -11
- data/lib/carrierwave/locale/ja.yml +0 -11
- data/lib/carrierwave/locale/nb.yml +0 -11
- data/lib/carrierwave/locale/nl.yml +0 -11
- data/lib/carrierwave/locale/pl.yml +0 -11
- data/lib/carrierwave/locale/pt-BR.yml +0 -11
- data/lib/carrierwave/locale/pt-PT.yml +0 -11
- data/lib/carrierwave/locale/ru.yml +0 -11
- data/lib/carrierwave/locale/sk.yml +0 -11
- data/lib/carrierwave/locale/tr.yml +0 -11
- data/lib/carrierwave/processing/mime_types.rb +0 -74
- data/lib/carrierwave/uploader/content_type_blacklist.rb +0 -48
- data/lib/carrierwave/uploader/content_type_whitelist.rb +0 -48
- data/lib/carrierwave/uploader/extension_blacklist.rb +0 -47
- data/lib/carrierwave/uploader/extension_whitelist.rb +0 -49
- data/lib/carrierwave/utilities/deprecation.rb +0 -18
@@ -0,0 +1,257 @@
|
|
1
|
+
module CarrierWave
|
2
|
+
|
3
|
+
# this is an internal class, used by CarrierWave::Mount so that
|
4
|
+
# we don't pollute the model with a lot of methods.
|
5
|
+
class Mounter # :nodoc:
|
6
|
+
class Single < Mounter # :nodoc
|
7
|
+
def identifier
|
8
|
+
uploaders.first&.identifier
|
9
|
+
end
|
10
|
+
|
11
|
+
def temporary_identifier
|
12
|
+
temporary_identifiers.first
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Multiple < Mounter # :nodoc
|
17
|
+
def identifier
|
18
|
+
uploaders.map(&:identifier).presence
|
19
|
+
end
|
20
|
+
|
21
|
+
def temporary_identifier
|
22
|
+
temporary_identifiers.presence
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.build(record, column)
|
27
|
+
if record.class.uploader_options[column][:multiple]
|
28
|
+
Multiple.new(record, column)
|
29
|
+
else
|
30
|
+
Single.new(record, column)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
attr_reader :column, :record, :remote_urls, :remove,
|
35
|
+
:integrity_errors, :processing_errors, :download_errors
|
36
|
+
attr_accessor :remote_request_headers, :uploader_options
|
37
|
+
|
38
|
+
def initialize(record, column)
|
39
|
+
@record = record
|
40
|
+
@column = column
|
41
|
+
@options = record.class.uploader_options[column]
|
42
|
+
@download_errors = []
|
43
|
+
@processing_errors = []
|
44
|
+
@integrity_errors = []
|
45
|
+
|
46
|
+
@removed_uploaders = []
|
47
|
+
@added_uploaders = []
|
48
|
+
end
|
49
|
+
|
50
|
+
def uploader_class
|
51
|
+
record.class.uploaders[column]
|
52
|
+
end
|
53
|
+
|
54
|
+
def blank_uploader
|
55
|
+
uploader_class.new(record, column)
|
56
|
+
end
|
57
|
+
|
58
|
+
def identifiers
|
59
|
+
uploaders.map(&:identifier)
|
60
|
+
end
|
61
|
+
|
62
|
+
def read_identifiers
|
63
|
+
[record.read_uploader(serialization_column)].flatten.reject(&:blank?)
|
64
|
+
end
|
65
|
+
|
66
|
+
def uploaders
|
67
|
+
@uploaders ||= read_identifiers.map do |identifier|
|
68
|
+
uploader = blank_uploader
|
69
|
+
uploader.retrieve_from_store!(identifier)
|
70
|
+
uploader
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def cache(new_files)
|
75
|
+
return if !new_files.is_a?(Array) && new_files.blank?
|
76
|
+
old_uploaders = uploaders
|
77
|
+
@uploaders = new_files.map do |new_file|
|
78
|
+
handle_error do
|
79
|
+
if new_file.is_a?(String)
|
80
|
+
if (uploader = old_uploaders.detect { |old_uploader| old_uploader.identifier == new_file })
|
81
|
+
uploader.staged = true
|
82
|
+
uploader
|
83
|
+
else
|
84
|
+
begin
|
85
|
+
uploader = blank_uploader
|
86
|
+
uploader.retrieve_from_cache!(new_file)
|
87
|
+
uploader
|
88
|
+
rescue CarrierWave::InvalidParameter
|
89
|
+
nil
|
90
|
+
end
|
91
|
+
end
|
92
|
+
else
|
93
|
+
uploader = blank_uploader
|
94
|
+
uploader.cache!(new_file)
|
95
|
+
uploader
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end.reject(&:blank?)
|
99
|
+
@removed_uploaders += (old_uploaders - @uploaders)
|
100
|
+
write_temporary_identifier
|
101
|
+
end
|
102
|
+
|
103
|
+
def cache_names
|
104
|
+
uploaders.map(&:cache_name).compact
|
105
|
+
end
|
106
|
+
|
107
|
+
def cache_names=(cache_names)
|
108
|
+
cache_names = cache_names.reject(&:blank?)
|
109
|
+
return if cache_names.blank?
|
110
|
+
clear_unstaged
|
111
|
+
cache_names.each do |cache_name|
|
112
|
+
uploader = blank_uploader
|
113
|
+
uploader.retrieve_from_cache!(cache_name)
|
114
|
+
@uploaders << uploader
|
115
|
+
rescue CarrierWave::InvalidParameter
|
116
|
+
# ignore
|
117
|
+
end
|
118
|
+
write_temporary_identifier
|
119
|
+
end
|
120
|
+
|
121
|
+
def remote_urls=(urls)
|
122
|
+
if urls.nil?
|
123
|
+
urls = []
|
124
|
+
else
|
125
|
+
urls = Array.wrap(urls).reject(&:blank?)
|
126
|
+
return if urls.blank?
|
127
|
+
end
|
128
|
+
@download_errors.clear
|
129
|
+
@remote_urls = urls
|
130
|
+
|
131
|
+
clear_unstaged
|
132
|
+
@remote_urls.zip(remote_request_headers || []) do |url, header|
|
133
|
+
handle_error do
|
134
|
+
uploader = blank_uploader
|
135
|
+
uploader.download!(url, header || {})
|
136
|
+
@uploaders << uploader
|
137
|
+
end
|
138
|
+
end
|
139
|
+
write_temporary_identifier
|
140
|
+
end
|
141
|
+
|
142
|
+
def store!
|
143
|
+
uploaders.each(&:store!)
|
144
|
+
end
|
145
|
+
|
146
|
+
def write_identifier
|
147
|
+
return if record.frozen?
|
148
|
+
|
149
|
+
clear! if remove?
|
150
|
+
|
151
|
+
additions, remains = uploaders.partition(&:cached?)
|
152
|
+
existing_identifiers = (@removed_uploaders + remains).map(&:identifier)
|
153
|
+
additions.each do |uploader|
|
154
|
+
uploader.deduplicate(existing_identifiers)
|
155
|
+
existing_identifiers << uploader.identifier
|
156
|
+
end
|
157
|
+
@added_uploaders += additions
|
158
|
+
|
159
|
+
record.write_uploader(serialization_column, identifier)
|
160
|
+
end
|
161
|
+
|
162
|
+
def urls(*args)
|
163
|
+
uploaders.map { |u| u.url(*args) }
|
164
|
+
end
|
165
|
+
|
166
|
+
def blank?
|
167
|
+
uploaders.none?(&:present?)
|
168
|
+
end
|
169
|
+
|
170
|
+
def remove=(value)
|
171
|
+
uploaders # Ensure that uploaders are initialized based on the current value
|
172
|
+
@remove = value
|
173
|
+
write_temporary_identifier
|
174
|
+
end
|
175
|
+
|
176
|
+
def remove?
|
177
|
+
remove.present? && (remove.to_s !~ /\A0|false$\z/)
|
178
|
+
end
|
179
|
+
|
180
|
+
def remove!
|
181
|
+
uploaders.each(&:remove!)
|
182
|
+
clear!
|
183
|
+
end
|
184
|
+
|
185
|
+
def clear!
|
186
|
+
@removed_uploaders += uploaders
|
187
|
+
@remove = nil
|
188
|
+
@uploaders = []
|
189
|
+
end
|
190
|
+
|
191
|
+
def reset_changes!
|
192
|
+
@removed_uploaders = []
|
193
|
+
@added_uploaders = []
|
194
|
+
end
|
195
|
+
|
196
|
+
def serialization_column
|
197
|
+
option(:mount_on) || column
|
198
|
+
end
|
199
|
+
|
200
|
+
def remove_previous
|
201
|
+
current_paths = uploaders.map(&:path)
|
202
|
+
@removed_uploaders
|
203
|
+
.reject {|uploader| current_paths.include?(uploader.path) }
|
204
|
+
.each { |uploader| uploader.remove! if uploader.remove_previously_stored_files_after_update }
|
205
|
+
reset_changes!
|
206
|
+
end
|
207
|
+
|
208
|
+
def remove_added
|
209
|
+
current_paths = (@removed_uploaders + uploaders.select(&:staged)).map(&:path)
|
210
|
+
@added_uploaders
|
211
|
+
.reject {|uploader| current_paths.include?(uploader.path) }
|
212
|
+
.each { |uploader| uploader.remove! }
|
213
|
+
reset_changes!
|
214
|
+
end
|
215
|
+
|
216
|
+
private
|
217
|
+
|
218
|
+
def option(name)
|
219
|
+
self.uploader_options ||= {}
|
220
|
+
self.uploader_options[name] ||= record.class.uploader_option(column, name)
|
221
|
+
end
|
222
|
+
|
223
|
+
def clear_unstaged
|
224
|
+
uploaders # Ensure that uploaders are initialized based on the current value
|
225
|
+
staged, unstaged = @uploaders.partition(&:staged)
|
226
|
+
@uploaders = staged
|
227
|
+
@removed_uploaders += unstaged
|
228
|
+
end
|
229
|
+
|
230
|
+
def handle_error
|
231
|
+
yield
|
232
|
+
rescue CarrierWave::DownloadError => e
|
233
|
+
@download_errors << e
|
234
|
+
raise e unless option(:ignore_download_errors)
|
235
|
+
rescue CarrierWave::ProcessingError => e
|
236
|
+
@processing_errors << e
|
237
|
+
raise e unless option(:ignore_processing_errors)
|
238
|
+
rescue CarrierWave::IntegrityError => e
|
239
|
+
@integrity_errors << e
|
240
|
+
raise e unless option(:ignore_integrity_errors)
|
241
|
+
end
|
242
|
+
|
243
|
+
def write_temporary_identifier
|
244
|
+
return if record.frozen?
|
245
|
+
|
246
|
+
record.write_uploader(serialization_column, temporary_identifier)
|
247
|
+
end
|
248
|
+
|
249
|
+
def temporary_identifiers
|
250
|
+
if remove?
|
251
|
+
[]
|
252
|
+
else
|
253
|
+
uploaders.map { |uploader| uploader.temporary_identifier }
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end # Mounter
|
257
|
+
end # CarrierWave
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
require 'active_record'
|
4
2
|
require 'carrierwave/validations/active_model'
|
5
3
|
|
@@ -8,10 +6,9 @@ module CarrierWave
|
|
8
6
|
|
9
7
|
include CarrierWave::Mount
|
10
8
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
def mount_uploader(column, uploader=nil, options={}, &block)
|
9
|
+
private
|
10
|
+
|
11
|
+
def mount_base(column, uploader=nil, options={}, &block)
|
15
12
|
super
|
16
13
|
|
17
14
|
alias_method :read_uploader, :read_attribute
|
@@ -27,45 +24,42 @@ module CarrierWave
|
|
27
24
|
|
28
25
|
after_save :"store_#{column}!"
|
29
26
|
before_save :"write_#{column}_identifier"
|
27
|
+
if ::ActiveRecord.try(:run_after_transaction_callbacks_in_order_defined)
|
28
|
+
after_commit :"remove_previously_stored_#{column}", :on => :update
|
29
|
+
after_commit :"reset_previous_changes_for_#{column}"
|
30
|
+
after_commit :"mark_remove_#{column}_false", :on => :update
|
31
|
+
else
|
32
|
+
after_commit :"mark_remove_#{column}_false", :on => :update
|
33
|
+
after_commit :"reset_previous_changes_for_#{column}"
|
34
|
+
after_commit :"remove_previously_stored_#{column}", :on => :update
|
35
|
+
end
|
30
36
|
after_commit :"remove_#{column}!", :on => :destroy
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
class_eval <<-RUBY, __FILE__, __LINE__+1
|
36
|
-
|
37
|
-
|
38
|
-
|
37
|
+
after_rollback :"remove_rolled_back_#{column}"
|
38
|
+
|
39
|
+
mod = Module.new
|
40
|
+
prepend mod
|
41
|
+
mod.class_eval <<-RUBY, __FILE__, __LINE__+1
|
42
|
+
# Reset cached mounter on record reload
|
43
|
+
def reload(*)
|
44
|
+
@_mounters = nil
|
39
45
|
super
|
40
46
|
end
|
41
47
|
|
42
|
-
|
43
|
-
|
44
|
-
|
48
|
+
# Reset cached mounter on record dup
|
49
|
+
def initialize_dup(other)
|
50
|
+
old_uploaders = _mounter(:"#{column}").uploaders
|
45
51
|
super
|
52
|
+
@_mounters[:"#{column}"] = nil
|
53
|
+
# The attribute needs to be cleared to prevent it from picked up as identifier
|
54
|
+
write_uploader(_mounter(:#{column}).serialization_column, nil)
|
55
|
+
_mounter(:"#{column}").cache(old_uploaders)
|
46
56
|
end
|
47
57
|
|
48
|
-
def
|
58
|
+
def write_#{column}_identifier
|
59
|
+
return unless has_attribute?(_mounter(:#{column}).serialization_column)
|
49
60
|
super
|
50
|
-
_mounter(:#{column}).remove = true
|
51
|
-
_mounter(:#{column}).write_identifier
|
52
|
-
end
|
53
|
-
|
54
|
-
def serializable_hash(options=nil)
|
55
|
-
hash = {}
|
56
|
-
|
57
|
-
except = options && options[:except] && Array.wrap(options[:except]).map(&:to_s)
|
58
|
-
only = options && options[:only] && Array.wrap(options[:only]).map(&:to_s)
|
59
|
-
|
60
|
-
self.class.uploaders.each do |column, uploader|
|
61
|
-
if (!only && !except) || (only && only.include?(column.to_s)) || (!only && except && !except.include?(column.to_s))
|
62
|
-
hash[column.to_s] = _mounter(column).uploader.serializable_hash
|
63
|
-
end
|
64
|
-
end
|
65
|
-
super(options).merge(hash)
|
66
61
|
end
|
67
62
|
RUBY
|
68
|
-
|
69
63
|
end
|
70
64
|
|
71
65
|
end # ActiveRecord
|