carrierwave 2.2.0 → 3.0.0
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.
Potentially problematic release.
This version of carrierwave might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +151 -63
- data/lib/carrierwave/compatibility/paperclip.rb +4 -2
- data/lib/carrierwave/downloader/base.rb +27 -13
- data/lib/carrierwave/downloader/remote_file.rb +12 -9
- data/lib/carrierwave/locale/en.yml +5 -3
- data/lib/carrierwave/mount.rb +31 -50
- data/lib/carrierwave/mounter.rb +115 -50
- data/lib/carrierwave/orm/activerecord.rb +12 -60
- data/lib/carrierwave/processing/mini_magick.rb +15 -13
- data/lib/carrierwave/processing/rmagick.rb +11 -15
- data/lib/carrierwave/processing/vips.rb +12 -12
- data/lib/carrierwave/sanitized_file.rb +50 -79
- data/lib/carrierwave/storage/abstract.rb +5 -5
- data/lib/carrierwave/storage/file.rb +6 -5
- data/lib/carrierwave/storage/fog.rb +78 -69
- data/lib/carrierwave/test/matchers.rb +11 -7
- data/lib/carrierwave/uploader/cache.rb +18 -10
- data/lib/carrierwave/uploader/callbacks.rb +1 -1
- data/lib/carrierwave/uploader/configuration.rb +10 -4
- data/lib/carrierwave/uploader/{content_type_whitelist.rb → content_type_allowlist.rb} +17 -15
- data/lib/carrierwave/uploader/{content_type_blacklist.rb → content_type_denylist.rb} +19 -14
- data/lib/carrierwave/uploader/dimension.rb +66 -0
- data/lib/carrierwave/uploader/{extension_whitelist.rb → extension_allowlist.rb} +17 -15
- data/lib/carrierwave/uploader/{extension_blacklist.rb → extension_denylist.rb} +18 -13
- data/lib/carrierwave/uploader/file_size.rb +2 -2
- data/lib/carrierwave/uploader/processing.rb +42 -7
- data/lib/carrierwave/uploader/proxy.rb +16 -3
- data/lib/carrierwave/uploader/store.rb +43 -6
- data/lib/carrierwave/uploader/url.rb +1 -1
- data/lib/carrierwave/uploader/versions.rb +137 -132
- data/lib/carrierwave/uploader.rb +10 -8
- data/lib/carrierwave/utilities/file_name.rb +47 -0
- data/lib/carrierwave/utilities/uri.rb +14 -11
- data/lib/carrierwave/utilities.rb +1 -0
- data/lib/carrierwave/validations/active_model.rb +4 -6
- data/lib/carrierwave/version.rb +1 -1
- data/lib/carrierwave.rb +9 -17
- data/lib/generators/uploader_generator.rb +3 -3
- metadata +54 -46
- /data/lib/generators/templates/{uploader.rb → uploader.rb.erb} +0 -0
@@ -11,7 +11,7 @@ module CarrierWave
|
|
11
11
|
prepend Module.new {
|
12
12
|
def initialize(*)
|
13
13
|
super
|
14
|
-
@file, @filename, @cache_id, @identifier = nil
|
14
|
+
@file, @filename, @cache_id, @identifier, @deduplication_index = nil
|
15
15
|
end
|
16
16
|
}
|
17
17
|
end
|
@@ -34,9 +34,25 @@ module CarrierWave
|
|
34
34
|
@filename
|
35
35
|
end
|
36
36
|
|
37
|
+
##
|
38
|
+
# Returns a filename which doesn't conflict with already-stored files.
|
39
|
+
#
|
40
|
+
# === Returns
|
41
|
+
#
|
42
|
+
# [String] the filename with suffix added for deduplication
|
43
|
+
#
|
44
|
+
def deduplicated_filename
|
45
|
+
return unless filename
|
46
|
+
|
47
|
+
parts = filename.split('.')
|
48
|
+
basename = parts.shift
|
49
|
+
basename.sub!(/ ?\(\d+\)\z/, '')
|
50
|
+
([basename.to_s + (@deduplication_index ? "(#{@deduplication_index})" : '')] + parts).join('.')
|
51
|
+
end
|
52
|
+
|
37
53
|
##
|
38
54
|
# Calculates the path where the file should be stored. If +for_file+ is given, it will be
|
39
|
-
# used as the
|
55
|
+
# used as the identifier, otherwise +CarrierWave::Uploader#identifier+ is assumed.
|
40
56
|
#
|
41
57
|
# === Parameters
|
42
58
|
#
|
@@ -46,7 +62,7 @@ module CarrierWave
|
|
46
62
|
#
|
47
63
|
# [String] the store path
|
48
64
|
#
|
49
|
-
def store_path(for_file=
|
65
|
+
def store_path(for_file=identifier)
|
50
66
|
File.join([store_dir, full_filename(for_file)].compact)
|
51
67
|
end
|
52
68
|
|
@@ -60,7 +76,7 @@ module CarrierWave
|
|
60
76
|
# [new_file (File, IOString, Tempfile)] any kind of file object
|
61
77
|
#
|
62
78
|
def store!(new_file=nil)
|
63
|
-
cache!(new_file) if new_file &&
|
79
|
+
cache!(new_file) if new_file && !cached?
|
64
80
|
if !cache_only && @file && @cache_id
|
65
81
|
with_callbacks(:store, new_file) do
|
66
82
|
new_file = storage.store!(@file)
|
@@ -69,7 +85,8 @@ module CarrierWave
|
|
69
85
|
cache_storage.delete_dir!(cache_path(nil))
|
70
86
|
end
|
71
87
|
@file = new_file
|
72
|
-
@
|
88
|
+
@identifier = storage.identifier
|
89
|
+
@cache_id = @deduplication_index = nil
|
73
90
|
@staged = false
|
74
91
|
end
|
75
92
|
end
|
@@ -89,10 +106,30 @@ module CarrierWave
|
|
89
106
|
end
|
90
107
|
end
|
91
108
|
|
109
|
+
##
|
110
|
+
# Look for a store path which doesn't collide with the given already-stored paths.
|
111
|
+
# It is done by adding a index number as the suffix.
|
112
|
+
# For example, if there's 'image.jpg' and the @deduplication_index is set to 2,
|
113
|
+
# The stored file will be named as 'image(2).jpg'.
|
114
|
+
#
|
115
|
+
# === Parameters
|
116
|
+
#
|
117
|
+
# [current_paths (Array[String])] List of paths for already-stored files
|
118
|
+
#
|
119
|
+
def deduplicate(current_paths)
|
120
|
+
@deduplication_index = nil
|
121
|
+
return unless current_paths.include?(store_path)
|
122
|
+
|
123
|
+
(2..current_paths.size + 1).each do |i|
|
124
|
+
@deduplication_index = i
|
125
|
+
break unless current_paths.include?(store_path)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
92
129
|
private
|
93
130
|
|
94
131
|
def full_filename(for_file)
|
95
|
-
for_file
|
132
|
+
forcing_extension(for_file)
|
96
133
|
end
|
97
134
|
|
98
135
|
def storage
|
@@ -1,6 +1,76 @@
|
|
1
1
|
module CarrierWave
|
2
2
|
module Uploader
|
3
3
|
module Versions
|
4
|
+
class Builder
|
5
|
+
def initialize(name)
|
6
|
+
@name = name
|
7
|
+
@options = {}
|
8
|
+
@blocks = []
|
9
|
+
@klass = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def configure(options, &block)
|
13
|
+
@options.merge!(options)
|
14
|
+
@blocks << block if block
|
15
|
+
@klass = nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def build(superclass)
|
19
|
+
return @klass if @klass
|
20
|
+
@klass = Class.new(superclass)
|
21
|
+
superclass.const_set("#{@name.to_s.camelize}VersionUploader", @klass)
|
22
|
+
|
23
|
+
@klass.version_names += [@name]
|
24
|
+
@klass.versions = {}
|
25
|
+
@klass.processors = []
|
26
|
+
@klass.version_options = @options
|
27
|
+
@klass.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
28
|
+
# Regardless of what is set in the parent uploader, do not enforce the
|
29
|
+
# move_to_cache config option on versions because it moves the original
|
30
|
+
# file to the version's target file.
|
31
|
+
#
|
32
|
+
# If you want to enforce this setting on versions, override this method
|
33
|
+
# in each version:
|
34
|
+
#
|
35
|
+
# version :thumb do
|
36
|
+
# def move_to_cache
|
37
|
+
# true
|
38
|
+
# end
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
def move_to_cache
|
42
|
+
false
|
43
|
+
end
|
44
|
+
|
45
|
+
# Need to rely on the parent version's identifier, as versions don't have its own one.
|
46
|
+
def identifier
|
47
|
+
parent_version.identifier
|
48
|
+
end
|
49
|
+
RUBY
|
50
|
+
@blocks.each { |block| @klass.class_eval(&block) }
|
51
|
+
@klass
|
52
|
+
end
|
53
|
+
|
54
|
+
def deep_dup
|
55
|
+
other = dup
|
56
|
+
other.instance_variable_set(:@blocks, @blocks.dup)
|
57
|
+
other
|
58
|
+
end
|
59
|
+
|
60
|
+
def method_missing(name, *args)
|
61
|
+
super
|
62
|
+
rescue NoMethodError => e
|
63
|
+
raise e.exception <<~ERROR
|
64
|
+
#{e.message}
|
65
|
+
If you're trying to configure a version, do it inside a block like `version(:thumb) { self.#{name} #{args.map(&:inspect).join(', ')} }`.
|
66
|
+
ERROR
|
67
|
+
end
|
68
|
+
|
69
|
+
def respond_to_missing?(*)
|
70
|
+
super
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
4
74
|
extend ActiveSupport::Concern
|
5
75
|
|
6
76
|
include CarrierWave::Uploader::Callbacks
|
@@ -11,9 +81,8 @@ module CarrierWave
|
|
11
81
|
self.versions = {}
|
12
82
|
self.version_names = []
|
13
83
|
|
14
|
-
attr_accessor :
|
84
|
+
attr_accessor :parent_version
|
15
85
|
|
16
|
-
after :cache, :assign_parent_cache_id
|
17
86
|
after :cache, :cache_versions!
|
18
87
|
after :store, :store_versions!
|
19
88
|
after :remove, :remove_versions!
|
@@ -23,7 +92,7 @@ module CarrierWave
|
|
23
92
|
prepend Module.new {
|
24
93
|
def initialize(*)
|
25
94
|
super
|
26
|
-
@versions
|
95
|
+
@versions = nil
|
27
96
|
end
|
28
97
|
}
|
29
98
|
end
|
@@ -51,80 +120,33 @@ module CarrierWave
|
|
51
120
|
# process :scale => [200, 200]
|
52
121
|
# end
|
53
122
|
#
|
123
|
+
# version :square, :unless => :invalid_image_type? do
|
124
|
+
# process :scale => [100, 100]
|
125
|
+
# end
|
126
|
+
#
|
54
127
|
# end
|
55
128
|
#
|
56
129
|
def version(name, options = {}, &block)
|
57
130
|
name = name.to_sym
|
58
|
-
|
131
|
+
versions[name] ||= Builder.new(name)
|
132
|
+
versions[name].configure(options, &block)
|
59
133
|
|
60
|
-
|
61
|
-
|
62
|
-
|
134
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
135
|
+
def #{name}
|
136
|
+
versions[:#{name}]
|
137
|
+
end
|
138
|
+
RUBY
|
63
139
|
|
64
|
-
|
65
|
-
versions.each do |name, version|
|
66
|
-
version.class_eval(&block)
|
67
|
-
version.recursively_apply_block_to_versions(&block)
|
68
|
-
end
|
140
|
+
versions[name]
|
69
141
|
end
|
70
142
|
|
71
143
|
private
|
72
144
|
|
73
|
-
def
|
74
|
-
|
75
|
-
|
76
|
-
|
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
|
109
|
-
end
|
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
|
123
|
-
|
124
|
-
# Add the current version hash to class attribute :versions
|
125
|
-
self.versions = versions.merge(name => uploader)
|
145
|
+
def inherited(subclass)
|
146
|
+
# To prevent subclass version changes affecting superclass versions
|
147
|
+
subclass.versions = versions.deep_dup
|
148
|
+
super
|
126
149
|
end
|
127
|
-
|
128
150
|
end # ClassMethods
|
129
151
|
|
130
152
|
##
|
@@ -138,7 +160,7 @@ module CarrierWave
|
|
138
160
|
return @versions if @versions
|
139
161
|
@versions = {}
|
140
162
|
self.class.versions.each do |name, version|
|
141
|
-
@versions[name] = version.new(model, mounted_as)
|
163
|
+
@versions[name] = version.build(self.class).new(model, mounted_as)
|
142
164
|
@versions[name].parent_version = self
|
143
165
|
end
|
144
166
|
@versions
|
@@ -161,25 +183,44 @@ module CarrierWave
|
|
161
183
|
#
|
162
184
|
# === Returns
|
163
185
|
#
|
164
|
-
# [Boolean] True when the version exists according to its :if condition
|
186
|
+
# [Boolean] True when the version exists according to its :if or :unless condition
|
165
187
|
#
|
166
188
|
def version_exists?(name)
|
167
189
|
name = name.to_sym
|
168
190
|
|
169
|
-
return false unless
|
191
|
+
return false unless versions.has_key?(name)
|
192
|
+
|
193
|
+
if_condition = versions[name].class.version_options[:if]
|
194
|
+
unless_condition = versions[name].class.version_options[:unless]
|
170
195
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
condition.call(self, :version => name, :file => file)
|
196
|
+
if if_condition
|
197
|
+
if if_condition.respond_to?(:call)
|
198
|
+
if_condition.call(self, :version => name, :file => file)
|
175
199
|
else
|
176
|
-
send(
|
200
|
+
send(if_condition, file)
|
201
|
+
end
|
202
|
+
elsif unless_condition
|
203
|
+
if unless_condition.respond_to?(:call)
|
204
|
+
!unless_condition.call(self, :version => name, :file => file)
|
205
|
+
else
|
206
|
+
!send(unless_condition, file)
|
177
207
|
end
|
178
208
|
else
|
179
209
|
true
|
180
210
|
end
|
181
211
|
end
|
182
212
|
|
213
|
+
##
|
214
|
+
# Copies the parent's cache_id when caching a version file.
|
215
|
+
# This behavior is not essential but it makes easier to understand
|
216
|
+
# that the cached files are generated by the single upload attempt.
|
217
|
+
#
|
218
|
+
def cache!(*args)
|
219
|
+
self.cache_id = parent_version.cache_id if parent_version
|
220
|
+
|
221
|
+
super
|
222
|
+
end
|
223
|
+
|
183
224
|
##
|
184
225
|
# When given a version name as a parameter, will return the url for that version
|
185
226
|
# This also works with nested versions.
|
@@ -221,60 +262,25 @@ module CarrierWave
|
|
221
262
|
# versions if their parameters somehow have changed.
|
222
263
|
#
|
223
264
|
def recreate_versions!(*names)
|
224
|
-
#
|
225
|
-
#
|
226
|
-
# processing a cached file
|
227
|
-
#
|
228
|
-
# The call to store! will trigger the necessary callbacks to both
|
229
|
-
# process this version and all sub-versions
|
265
|
+
# As well as specified versions, we need to reprocess versions
|
266
|
+
# that are the source of another version.
|
230
267
|
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
reset_versions_to_cache_and_store
|
235
|
-
else
|
236
|
-
cache! if !cached?
|
237
|
-
store!
|
268
|
+
self.cache_id = CarrierWave.generate_cache_id
|
269
|
+
derived_versions.each do |name, v|
|
270
|
+
v.cache!(file) if names.empty? || !(v.descendant_version_names & names).empty?
|
238
271
|
end
|
239
|
-
|
240
|
-
|
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
|
+
active_versions.each do |name, v|
|
273
|
+
v.store! if names.empty? || names.include?(name)
|
272
274
|
end
|
275
|
+
ensure
|
276
|
+
@cache_id = nil
|
273
277
|
end
|
274
278
|
|
275
|
-
|
276
|
-
|
277
|
-
|
279
|
+
protected
|
280
|
+
|
281
|
+
def descendant_version_names
|
282
|
+
[version_name] + derived_versions.flat_map do |name, version|
|
283
|
+
version.descendant_version_names
|
278
284
|
end
|
279
285
|
end
|
280
286
|
|
@@ -284,16 +290,18 @@ module CarrierWave
|
|
284
290
|
end
|
285
291
|
end
|
286
292
|
|
287
|
-
|
293
|
+
private
|
294
|
+
|
295
|
+
def derived_versions
|
288
296
|
active_versions.reject do |name, v|
|
289
297
|
v.class.version_options[:from_version]
|
290
|
-
end.to_a +
|
298
|
+
end.to_a + active_sibling_versions.select do |name, v|
|
291
299
|
v.class.version_options[:from_version] == self.class.version_names.last
|
292
300
|
end.to_a
|
293
301
|
end
|
294
302
|
|
295
|
-
def
|
296
|
-
parent_version
|
303
|
+
def active_sibling_versions
|
304
|
+
parent_version&.active_versions || []
|
297
305
|
end
|
298
306
|
|
299
307
|
def full_filename(for_file)
|
@@ -305,14 +313,11 @@ module CarrierWave
|
|
305
313
|
end
|
306
314
|
|
307
315
|
def cache_versions!(new_file)
|
308
|
-
|
309
|
-
v.send(:cache_id=, @cache_id)
|
310
|
-
v.cache!(new_file)
|
311
|
-
end
|
316
|
+
derived_versions.each { |name, v| v.cache!(new_file) }
|
312
317
|
end
|
313
318
|
|
314
319
|
def store_versions!(new_file)
|
315
|
-
|
320
|
+
active_versions.each { |name, v| v.store!(new_file) }
|
316
321
|
end
|
317
322
|
|
318
323
|
def remove_versions!
|
data/lib/carrierwave/uploader.rb
CHANGED
@@ -7,11 +7,12 @@ require "carrierwave/uploader/cache"
|
|
7
7
|
require "carrierwave/uploader/store"
|
8
8
|
require "carrierwave/uploader/download"
|
9
9
|
require "carrierwave/uploader/remove"
|
10
|
-
require "carrierwave/uploader/
|
11
|
-
require "carrierwave/uploader/
|
12
|
-
require "carrierwave/uploader/
|
13
|
-
require "carrierwave/uploader/
|
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
14
|
require "carrierwave/uploader/file_size"
|
15
|
+
require "carrierwave/uploader/dimension"
|
15
16
|
require "carrierwave/uploader/processing"
|
16
17
|
require "carrierwave/uploader/versions"
|
17
18
|
require "carrierwave/uploader/default_url"
|
@@ -52,11 +53,12 @@ module CarrierWave
|
|
52
53
|
include CarrierWave::Uploader::Store
|
53
54
|
include CarrierWave::Uploader::Download
|
54
55
|
include CarrierWave::Uploader::Remove
|
55
|
-
include CarrierWave::Uploader::
|
56
|
-
include CarrierWave::Uploader::
|
57
|
-
include CarrierWave::Uploader::
|
58
|
-
include CarrierWave::Uploader::
|
56
|
+
include CarrierWave::Uploader::ExtensionAllowlist
|
57
|
+
include CarrierWave::Uploader::ExtensionDenylist
|
58
|
+
include CarrierWave::Uploader::ContentTypeAllowlist
|
59
|
+
include CarrierWave::Uploader::ContentTypeDenylist
|
59
60
|
include CarrierWave::Uploader::FileSize
|
61
|
+
include CarrierWave::Uploader::Dimension
|
60
62
|
include CarrierWave::Uploader::Processing
|
61
63
|
include CarrierWave::Uploader::Versions
|
62
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
|
@@ -3,20 +3,23 @@ require 'uri'
|
|
3
3
|
module CarrierWave
|
4
4
|
module Utilities
|
5
5
|
module Uri
|
6
|
-
|
7
|
-
|
8
|
-
|
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
|
9
10
|
|
10
11
|
private
|
12
|
+
|
11
13
|
def encode_path(path)
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
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
|
20
|
+
|
21
|
+
def decode_uri(str)
|
22
|
+
URI::DEFAULT_PARSER.unescape(str)
|
20
23
|
end
|
21
24
|
end # Uri
|
22
25
|
end # Utilities
|
@@ -12,8 +12,7 @@ module CarrierWave
|
|
12
12
|
|
13
13
|
def validate_each(record, attribute, value)
|
14
14
|
record.__send__("#{attribute}_processing_errors").each do |e|
|
15
|
-
message
|
16
|
-
record.errors.add(attribute, message)
|
15
|
+
record.errors.add(attribute, :carrierwave_processing_error, message: (e.message != e.class.to_s) && e.message)
|
17
16
|
end
|
18
17
|
end
|
19
18
|
end
|
@@ -22,8 +21,7 @@ module CarrierWave
|
|
22
21
|
|
23
22
|
def validate_each(record, attribute, value)
|
24
23
|
record.__send__("#{attribute}_integrity_errors").each do |e|
|
25
|
-
message
|
26
|
-
record.errors.add(attribute, message)
|
24
|
+
record.errors.add(attribute, :carrierwave_integrity_error, message: (e.message != e.class.to_s) && e.message)
|
27
25
|
end
|
28
26
|
end
|
29
27
|
end
|
@@ -32,8 +30,7 @@ module CarrierWave
|
|
32
30
|
|
33
31
|
def validate_each(record, attribute, value)
|
34
32
|
record.__send__("#{attribute}_download_errors").each do |e|
|
35
|
-
message
|
36
|
-
record.errors.add(attribute, message)
|
33
|
+
record.errors.add(attribute, :carrierwave_download_error, message: (e.message != e.class.to_s) && e.message)
|
37
34
|
end
|
38
35
|
end
|
39
36
|
end
|
@@ -58,6 +55,7 @@ module CarrierWave
|
|
58
55
|
def validates_processing_of(*attr_names)
|
59
56
|
validates_with ProcessingValidator, _merge_attributes(attr_names)
|
60
57
|
end
|
58
|
+
|
61
59
|
#
|
62
60
|
##
|
63
61
|
# Makes the record invalid if the remote file couldn't be downloaded
|
data/lib/carrierwave/version.rb
CHANGED
data/lib/carrierwave.rb
CHANGED
@@ -25,16 +25,7 @@ module CarrierWave
|
|
25
25
|
|
26
26
|
end
|
27
27
|
|
28
|
-
if defined?(
|
29
|
-
|
30
|
-
CarrierWave.root = Merb.dir_for(:public)
|
31
|
-
Merb::BootLoader.before_app_loads do
|
32
|
-
# Setup path for uploaders and load all of them before classes are loaded
|
33
|
-
Merb.push_path(:uploaders, Merb.root / 'app' / 'uploaders', '*.rb')
|
34
|
-
Dir.glob(File.join(Merb.load_paths[:uploaders])).each {|f| require f }
|
35
|
-
end
|
36
|
-
|
37
|
-
elsif defined?(Jets)
|
28
|
+
if defined?(Jets)
|
38
29
|
|
39
30
|
module CarrierWave
|
40
31
|
class Turbine < Jets::Turbine
|
@@ -84,13 +75,14 @@ elsif defined?(Sinatra)
|
|
84
75
|
CarrierWave.root = File.join(PADRINO_ROOT, "public")
|
85
76
|
else
|
86
77
|
|
87
|
-
CarrierWave.root =
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
78
|
+
CarrierWave.root =
|
79
|
+
if Sinatra::Application.respond_to?(:public_folder)
|
80
|
+
# Sinatra >= 1.3
|
81
|
+
Sinatra::Application.public_folder
|
82
|
+
else
|
83
|
+
# Sinatra < 1.3
|
84
|
+
Sinatra::Application.public
|
85
|
+
end
|
94
86
|
end
|
95
87
|
end
|
96
88
|
|