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.
- checksums.yaml +5 -5
- data/README.md +307 -121
- data/lib/carrierwave/compatibility/paperclip.rb +0 -2
- data/lib/carrierwave/downloader/base.rb +83 -0
- data/lib/carrierwave/downloader/remote_file.rb +65 -0
- data/lib/carrierwave/error.rb +1 -0
- data/lib/carrierwave/locale/en.yml +7 -4
- data/lib/carrierwave/mount.rb +229 -180
- data/lib/carrierwave/mounter.rb +188 -0
- data/lib/carrierwave/orm/activerecord.rb +59 -24
- data/lib/carrierwave/processing/mini_magick.rb +137 -83
- data/lib/carrierwave/processing/rmagick.rb +65 -8
- data/lib/carrierwave/processing.rb +0 -1
- data/lib/carrierwave/sanitized_file.rb +67 -32
- data/lib/carrierwave/storage/abstract.rb +15 -2
- data/lib/carrierwave/storage/file.rb +69 -2
- data/lib/carrierwave/storage/fog.rb +177 -39
- data/lib/carrierwave/storage.rb +1 -7
- data/lib/carrierwave/test/matchers.rb +77 -12
- data/lib/carrierwave/uploader/cache.rb +74 -38
- data/lib/carrierwave/uploader/callbacks.rb +0 -2
- data/lib/carrierwave/uploader/configuration.rb +71 -13
- data/lib/carrierwave/uploader/content_type_blacklist.rb +48 -0
- data/lib/carrierwave/uploader/content_type_whitelist.rb +48 -0
- data/lib/carrierwave/uploader/default_url.rb +3 -5
- data/lib/carrierwave/uploader/download.rb +4 -74
- data/lib/carrierwave/uploader/extension_blacklist.rb +14 -10
- data/lib/carrierwave/uploader/extension_whitelist.rb +13 -10
- data/lib/carrierwave/uploader/file_size.rb +43 -0
- data/lib/carrierwave/uploader/mountable.rb +13 -8
- data/lib/carrierwave/uploader/processing.rb +10 -10
- data/lib/carrierwave/uploader/proxy.rb +6 -8
- data/lib/carrierwave/uploader/remove.rb +0 -2
- data/lib/carrierwave/uploader/serialization.rb +2 -4
- data/lib/carrierwave/uploader/store.rb +17 -24
- data/lib/carrierwave/uploader/url.rb +3 -5
- data/lib/carrierwave/uploader/versions.rb +123 -93
- data/lib/carrierwave/uploader.rb +6 -2
- data/lib/carrierwave/utilities/uri.rb +5 -6
- data/lib/carrierwave/utilities.rb +0 -3
- data/lib/carrierwave/validations/active_model.rb +3 -5
- data/lib/carrierwave/version.rb +1 -1
- data/lib/carrierwave.rb +34 -8
- data/lib/generators/templates/uploader.rb +4 -8
- metadata +130 -57
- 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/utilities/deprecation.rb +0 -18
@@ -1,7 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require "fog"
|
4
|
-
|
5
1
|
module CarrierWave
|
6
2
|
module Storage
|
7
3
|
|
@@ -20,6 +16,8 @@ module CarrierWave
|
|
20
16
|
# [:fog_authenticated_url_expiration] (optional) time (in seconds) that authenticated urls
|
21
17
|
# will be valid, when fog_public is false and provider is AWS or Google, defaults to 600
|
22
18
|
# [:fog_use_ssl_for_aws] (optional) #public_url will use https for the AWS generated URL]
|
19
|
+
# [:fog_aws_accelerate] (optional) #public_url will use s3-accelerate subdomain
|
20
|
+
# instead of s3, defaults to false
|
23
21
|
#
|
24
22
|
#
|
25
23
|
# AWS credentials contain the following keys:
|
@@ -27,7 +25,7 @@ module CarrierWave
|
|
27
25
|
# [:aws_access_key_id]
|
28
26
|
# [:aws_secret_access_key]
|
29
27
|
# [:region] (optional) defaults to 'us-east-1'
|
30
|
-
# :region should be one of ['eu-west-1', 'us-east-1', 'ap-southeast-1', 'us-west-1', 'ap-northeast-1']
|
28
|
+
# :region should be one of ['eu-west-1', 'us-east-1', 'ap-southeast-1', 'us-west-1', 'ap-northeast-1', 'eu-central-1']
|
31
29
|
#
|
32
30
|
#
|
33
31
|
# Google credentials contain the following keys:
|
@@ -62,6 +60,14 @@ module CarrierWave
|
|
62
60
|
def connection_cache
|
63
61
|
@connection_cache ||= {}
|
64
62
|
end
|
63
|
+
|
64
|
+
def eager_load
|
65
|
+
# see #1198. This will hopefully no longer be necessary in future release of fog
|
66
|
+
fog_credentials = CarrierWave::Uploader::Base.fog_credentials
|
67
|
+
if fog_credentials.present?
|
68
|
+
CarrierWave::Storage::Fog.connection_cache[fog_credentials] ||= ::Fog::Storage.new(fog_credentials)
|
69
|
+
end
|
70
|
+
end
|
65
71
|
end
|
66
72
|
|
67
73
|
##
|
@@ -96,6 +102,57 @@ module CarrierWave
|
|
96
102
|
CarrierWave::Storage::Fog::File.new(uploader, self, uploader.store_path(identifier))
|
97
103
|
end
|
98
104
|
|
105
|
+
##
|
106
|
+
# Stores given file to cache directory.
|
107
|
+
#
|
108
|
+
# === Parameters
|
109
|
+
#
|
110
|
+
# [new_file (File, IOString, Tempfile)] any kind of file object
|
111
|
+
#
|
112
|
+
# === Returns
|
113
|
+
#
|
114
|
+
# [CarrierWave::SanitizedFile] a sanitized file
|
115
|
+
#
|
116
|
+
def cache!(new_file)
|
117
|
+
f = CarrierWave::Storage::Fog::File.new(uploader, self, uploader.cache_path)
|
118
|
+
f.store(new_file)
|
119
|
+
f
|
120
|
+
end
|
121
|
+
|
122
|
+
##
|
123
|
+
# Retrieves the file with the given cache_name from the cache.
|
124
|
+
#
|
125
|
+
# === Parameters
|
126
|
+
#
|
127
|
+
# [cache_name (String)] uniquely identifies a cache file
|
128
|
+
#
|
129
|
+
# === Raises
|
130
|
+
#
|
131
|
+
# [CarrierWave::InvalidParameter] if the cache_name is incorrectly formatted.
|
132
|
+
#
|
133
|
+
def retrieve_from_cache!(identifier)
|
134
|
+
CarrierWave::Storage::Fog::File.new(uploader, self, uploader.cache_path(identifier))
|
135
|
+
end
|
136
|
+
|
137
|
+
##
|
138
|
+
# Deletes a cache dir
|
139
|
+
#
|
140
|
+
def delete_dir!(path)
|
141
|
+
# do nothing, because there's no such things as 'empty directory'
|
142
|
+
end
|
143
|
+
|
144
|
+
def clean_cache!(seconds)
|
145
|
+
connection.directories.new(
|
146
|
+
:key => uploader.fog_directory,
|
147
|
+
:public => uploader.fog_public
|
148
|
+
).files.all(:prefix => uploader.cache_dir).each do |file|
|
149
|
+
# generate_cache_id returns key formated TIMEINT-PID(-COUNTER)-RND
|
150
|
+
time = file.key.scan(/(\d+)-\d+-\d+(?:-\d+)?/).first.map { |t| t.to_i }
|
151
|
+
time = Time.at(*time)
|
152
|
+
file.destroy if time < (Time.now.utc - seconds)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
99
156
|
def connection
|
100
157
|
@connection ||= begin
|
101
158
|
options = credentials = uploader.fog_credentials
|
@@ -104,6 +161,8 @@ module CarrierWave
|
|
104
161
|
end
|
105
162
|
|
106
163
|
class File
|
164
|
+
DEFAULT_S3_REGION = 'us-east-1'
|
165
|
+
|
107
166
|
include CarrierWave::Utilities::Uri
|
108
167
|
|
109
168
|
##
|
@@ -128,7 +187,7 @@ module CarrierWave
|
|
128
187
|
|
129
188
|
##
|
130
189
|
# Return a temporary authenticated url to a private file, if available
|
131
|
-
# Only supported for AWS, Rackspace and
|
190
|
+
# Only supported for AWS, Rackspace, Google, AzureRM and Aliyun providers
|
132
191
|
#
|
133
192
|
# === Returns
|
134
193
|
#
|
@@ -137,19 +196,28 @@ module CarrierWave
|
|
137
196
|
# [NilClass] no authenticated url available
|
138
197
|
#
|
139
198
|
def authenticated_url(options = {})
|
140
|
-
if ['AWS', 'Google', 'Rackspace', 'OpenStack'].include?(@uploader.fog_credentials[:provider])
|
199
|
+
if ['AWS', 'Google', 'Rackspace', 'OpenStack', 'AzureRM', 'Aliyun', 'backblaze'].include?(@uploader.fog_credentials[:provider])
|
141
200
|
# avoid a get by using local references
|
142
201
|
local_directory = connection.directories.new(:key => @uploader.fog_directory)
|
143
202
|
local_file = local_directory.files.new(:key => path)
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
203
|
+
expire_at = options[:expire_at] || ::Fog::Time.now + @uploader.fog_authenticated_url_expiration
|
204
|
+
case @uploader.fog_credentials[:provider]
|
205
|
+
when 'AWS', 'Google'
|
206
|
+
# Older versions of fog-google do not support options as a parameter
|
207
|
+
if url_options_supported?(local_file)
|
208
|
+
local_file.url(expire_at, options)
|
209
|
+
else
|
210
|
+
warn "Options hash not supported in #{local_file.class}. You may need to upgrade your Fog provider."
|
211
|
+
local_file.url(expire_at)
|
212
|
+
end
|
213
|
+
when 'Rackspace', 'OpenStack'
|
214
|
+
connection.get_object_https_url(@uploader.fog_directory, path, expire_at, options)
|
215
|
+
when 'Aliyun'
|
216
|
+
expire_at = expire_at - Time.now
|
217
|
+
local_file.url(expire_at)
|
218
|
+
else
|
219
|
+
local_file.url(expire_at)
|
150
220
|
end
|
151
|
-
else
|
152
|
-
nil
|
153
221
|
end
|
154
222
|
end
|
155
223
|
|
@@ -161,7 +229,7 @@ module CarrierWave
|
|
161
229
|
# [String] value of content-type
|
162
230
|
#
|
163
231
|
def content_type
|
164
|
-
@content_type || file.content_type
|
232
|
+
@content_type || file.try(:content_type)
|
165
233
|
end
|
166
234
|
|
167
235
|
##
|
@@ -184,7 +252,9 @@ module CarrierWave
|
|
184
252
|
#
|
185
253
|
def delete
|
186
254
|
# avoid a get by just using local reference
|
187
|
-
directory.files.new(:key => path).destroy
|
255
|
+
directory.files.new(:key => path).destroy.tap do |result|
|
256
|
+
@file = nil if result
|
257
|
+
end
|
188
258
|
end
|
189
259
|
|
190
260
|
##
|
@@ -215,7 +285,7 @@ module CarrierWave
|
|
215
285
|
end
|
216
286
|
|
217
287
|
def initialize(uploader, base, path)
|
218
|
-
@uploader, @base, @path = uploader, base, path
|
288
|
+
@uploader, @base, @path, @content_type = uploader, base, path, nil
|
219
289
|
end
|
220
290
|
|
221
291
|
##
|
@@ -225,6 +295,16 @@ module CarrierWave
|
|
225
295
|
#
|
226
296
|
# [String] contents of file
|
227
297
|
def read
|
298
|
+
file_body = file.body
|
299
|
+
|
300
|
+
return if file_body.nil?
|
301
|
+
return file_body unless file_body.is_a?(::File)
|
302
|
+
|
303
|
+
# Fog::Storage::XXX::File#body could return the source file which was upoloaded to the remote server.
|
304
|
+
read_source_file(file_body) if ::File.exist?(file_body.path)
|
305
|
+
|
306
|
+
# If the source file doesn't exist, the remote content is read
|
307
|
+
@file = nil # rubocop:disable Gitlab/ModuleWithInstanceVariables
|
228
308
|
file.body
|
229
309
|
end
|
230
310
|
|
@@ -236,7 +316,7 @@ module CarrierWave
|
|
236
316
|
# [Integer] size of file body
|
237
317
|
#
|
238
318
|
def size
|
239
|
-
file.content_length
|
319
|
+
file.nil? ? 0 : file.content_length
|
240
320
|
end
|
241
321
|
|
242
322
|
##
|
@@ -246,7 +326,7 @@ module CarrierWave
|
|
246
326
|
#
|
247
327
|
# [Boolean] true if file exists or false
|
248
328
|
def exists?
|
249
|
-
!!
|
329
|
+
!!file
|
250
330
|
end
|
251
331
|
|
252
332
|
##
|
@@ -256,15 +336,19 @@ module CarrierWave
|
|
256
336
|
#
|
257
337
|
# [Boolean] true on success or raises error
|
258
338
|
def store(new_file)
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
339
|
+
if new_file.is_a?(self.class)
|
340
|
+
new_file.copy_to(path)
|
341
|
+
else
|
342
|
+
fog_file = new_file.to_file
|
343
|
+
@content_type ||= new_file.content_type
|
344
|
+
@file = directory.files.create({
|
345
|
+
:body => fog_file ? fog_file : new_file.read,
|
346
|
+
:content_type => @content_type,
|
347
|
+
:key => path,
|
348
|
+
:public => @uploader.fog_public
|
349
|
+
}.merge(@uploader.fog_attributes))
|
350
|
+
fog_file.close if fog_file && !fog_file.closed?
|
351
|
+
end
|
268
352
|
true
|
269
353
|
end
|
270
354
|
|
@@ -287,23 +371,35 @@ module CarrierWave
|
|
287
371
|
end
|
288
372
|
else
|
289
373
|
# AWS/Google optimized for speed over correctness
|
290
|
-
case
|
374
|
+
case fog_provider
|
291
375
|
when 'AWS'
|
292
376
|
# check if some endpoint is set in fog_credentials
|
293
377
|
if @uploader.fog_credentials.has_key?(:endpoint)
|
294
378
|
"#{@uploader.fog_credentials[:endpoint]}/#{@uploader.fog_directory}/#{encoded_path}"
|
295
379
|
else
|
296
380
|
protocol = @uploader.fog_use_ssl_for_aws ? "https" : "http"
|
381
|
+
|
382
|
+
subdomain_regex = /^(?:[a-z]|\d(?!\d{0,2}(?:\d{1,3}){3}$))(?:[a-z0-9\.]|(?![\-])|\-(?![\.])){1,61}[a-z0-9]$/
|
383
|
+
valid_subdomain = @uploader.fog_directory.to_s =~ subdomain_regex && !(protocol == 'https' && @uploader.fog_directory =~ /\./)
|
384
|
+
|
297
385
|
# if directory is a valid subdomain, use that style for access
|
298
|
-
if
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
386
|
+
if valid_subdomain
|
387
|
+
s3_subdomain = @uploader.fog_aws_accelerate ? "s3-accelerate" : "s3"
|
388
|
+
"#{protocol}://#{@uploader.fog_directory}.#{s3_subdomain}.amazonaws.com/#{encoded_path}"
|
389
|
+
else # directory is not a valid subdomain, so use path style for access
|
390
|
+
region = @uploader.fog_credentials[:region].to_s
|
391
|
+
host = case region
|
392
|
+
when DEFAULT_S3_REGION, ''
|
393
|
+
's3.amazonaws.com'
|
394
|
+
else
|
395
|
+
"s3.#{region}.amazonaws.com"
|
396
|
+
end
|
397
|
+
"#{protocol}://#{host}/#{@uploader.fog_directory}/#{encoded_path}"
|
303
398
|
end
|
304
399
|
end
|
305
400
|
when 'Google'
|
306
|
-
|
401
|
+
# https://cloud.google.com/storage/docs/access-public-data
|
402
|
+
"https://storage.googleapis.com/#{@uploader.fog_directory}/#{encoded_path}"
|
307
403
|
else
|
308
404
|
# avoid a get by just using local reference
|
309
405
|
directory.files.new(:key => path).public_url
|
@@ -338,9 +434,24 @@ module CarrierWave
|
|
338
434
|
# [NilClass] no file name available
|
339
435
|
#
|
340
436
|
def filename(options = {})
|
341
|
-
|
342
|
-
|
343
|
-
|
437
|
+
return unless file_url = url(options)
|
438
|
+
CGI.unescape(file_url.split('?').first).gsub(/.*\/(.*?$)/, '\1')
|
439
|
+
end
|
440
|
+
|
441
|
+
##
|
442
|
+
# Creates a copy of this file and returns it.
|
443
|
+
#
|
444
|
+
# === Parameters
|
445
|
+
#
|
446
|
+
# [new_path (String)] The path where the file should be copied to.
|
447
|
+
#
|
448
|
+
# === Returns
|
449
|
+
#
|
450
|
+
# @return [CarrierWave::Storage::Fog::File] the location where the file will be stored.
|
451
|
+
#
|
452
|
+
def copy_to(new_path)
|
453
|
+
connection.copy_object(@uploader.fog_directory, file.key, @uploader.fog_directory, new_path, acl_header)
|
454
|
+
CarrierWave::Storage::Fog::File.new(@uploader, @base, new_path)
|
344
455
|
end
|
345
456
|
|
346
457
|
private
|
@@ -383,6 +494,33 @@ module CarrierWave
|
|
383
494
|
@file ||= directory.files.head(path)
|
384
495
|
end
|
385
496
|
|
497
|
+
def acl_header
|
498
|
+
if fog_provider == 'AWS'
|
499
|
+
{ 'x-amz-acl' => @uploader.fog_public ? 'public-read' : 'private' }
|
500
|
+
else
|
501
|
+
{}
|
502
|
+
end
|
503
|
+
end
|
504
|
+
|
505
|
+
def fog_provider
|
506
|
+
@uploader.fog_credentials[:provider].to_s
|
507
|
+
end
|
508
|
+
|
509
|
+
def read_source_file(file_body)
|
510
|
+
return unless ::File.exist?(file_body.path)
|
511
|
+
|
512
|
+
begin
|
513
|
+
file_body = ::File.open(file_body.path) if file_body.closed? # Reopen if it's already closed
|
514
|
+
file_body.read
|
515
|
+
ensure
|
516
|
+
file_body.close
|
517
|
+
end
|
518
|
+
end
|
519
|
+
|
520
|
+
def url_options_supported?(local_file)
|
521
|
+
parameters = local_file.method(:url).parameters
|
522
|
+
parameters.count == 2 && parameters[1].include?(:options)
|
523
|
+
end
|
386
524
|
end
|
387
525
|
|
388
526
|
end # Fog
|
data/lib/carrierwave/storage.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
module CarrierWave
|
4
2
|
module Test
|
5
3
|
|
@@ -23,13 +21,16 @@ module CarrierWave
|
|
23
21
|
"expected #{@actual.inspect} to be identical to #{@expected.inspect}"
|
24
22
|
end
|
25
23
|
|
26
|
-
def
|
24
|
+
def failure_message_when_negated
|
27
25
|
"expected #{@actual.inspect} to not be identical to #{@expected.inspect}"
|
28
26
|
end
|
29
27
|
|
30
28
|
def description
|
31
29
|
"be identical to #{@expected.inspect}"
|
32
30
|
end
|
31
|
+
|
32
|
+
# RSpec 2 compatibility:
|
33
|
+
alias_method :negative_failure_message, :failure_message_when_negated
|
33
34
|
end
|
34
35
|
|
35
36
|
def be_identical_to(expected)
|
@@ -51,13 +52,16 @@ module CarrierWave
|
|
51
52
|
"expected #{@actual.current_path.inspect} to have permissions #{@expected.to_s(8)}, but they were #{(File.stat(@actual.path).mode & 0777).to_s(8)}"
|
52
53
|
end
|
53
54
|
|
54
|
-
def
|
55
|
+
def failure_message_when_negated
|
55
56
|
"expected #{@actual.current_path.inspect} not to have permissions #{@expected.to_s(8)}, but it did"
|
56
57
|
end
|
57
58
|
|
58
59
|
def description
|
59
60
|
"have permissions #{@expected.to_s(8)}"
|
60
61
|
end
|
62
|
+
|
63
|
+
# RSpec 2 compatibility:
|
64
|
+
alias_method :negative_failure_message, :failure_message_when_negated
|
61
65
|
end
|
62
66
|
|
63
67
|
def have_permissions(expected)
|
@@ -79,13 +83,16 @@ module CarrierWave
|
|
79
83
|
"expected #{File.dirname @actual.current_path.inspect} to have permissions #{@expected.to_s(8)}, but they were #{(File.stat(@actual.path).mode & 0777).to_s(8)}"
|
80
84
|
end
|
81
85
|
|
82
|
-
def
|
86
|
+
def failure_message_when_negated
|
83
87
|
"expected #{File.dirname @actual.current_path.inspect} not to have permissions #{@expected.to_s(8)}, but it did"
|
84
88
|
end
|
85
89
|
|
86
90
|
def description
|
87
91
|
"have permissions #{@expected.to_s(8)}"
|
88
92
|
end
|
93
|
+
|
94
|
+
# RSpec 2 compatibility:
|
95
|
+
alias_method :negative_failure_message, :failure_message_when_negated
|
89
96
|
end
|
90
97
|
|
91
98
|
def have_directory_permissions(expected)
|
@@ -110,13 +117,16 @@ module CarrierWave
|
|
110
117
|
"expected #{@actual.current_path.inspect} to be no larger than #{@width} by #{@height}, but it was #{@actual_width} by #{@actual_height}."
|
111
118
|
end
|
112
119
|
|
113
|
-
def
|
120
|
+
def failure_message_when_negated
|
114
121
|
"expected #{@actual.current_path.inspect} to be larger than #{@width} by #{@height}, but it wasn't."
|
115
122
|
end
|
116
123
|
|
117
124
|
def description
|
118
125
|
"be no larger than #{@width} by #{@height}"
|
119
126
|
end
|
127
|
+
|
128
|
+
# RSpec 2 compatibility:
|
129
|
+
alias_method :negative_failure_message, :failure_message_when_negated
|
120
130
|
end
|
121
131
|
|
122
132
|
def be_no_larger_than(width, height)
|
@@ -141,13 +151,16 @@ module CarrierWave
|
|
141
151
|
"expected #{@actual.current_path.inspect} to have an exact size of #{@width} by #{@height}, but it was #{@actual_width} by #{@actual_height}."
|
142
152
|
end
|
143
153
|
|
144
|
-
def
|
154
|
+
def failure_message_when_negated
|
145
155
|
"expected #{@actual.current_path.inspect} not to have an exact size of #{@width} by #{@height}, but it did."
|
146
156
|
end
|
147
157
|
|
148
158
|
def description
|
149
159
|
"have an exact size of #{@width} by #{@height}"
|
150
160
|
end
|
161
|
+
|
162
|
+
# RSpec 2 compatibility:
|
163
|
+
alias_method :negative_failure_message, :failure_message_when_negated
|
151
164
|
end
|
152
165
|
|
153
166
|
def have_dimensions(width, height)
|
@@ -171,13 +184,16 @@ module CarrierWave
|
|
171
184
|
"expected #{@actual.current_path.inspect} to have an exact size of #{@height}, but it was #{@actual_height}."
|
172
185
|
end
|
173
186
|
|
174
|
-
def
|
187
|
+
def failure_message_when_negated
|
175
188
|
"expected #{@actual.current_path.inspect} not to have an exact size of #{@height}, but it did."
|
176
189
|
end
|
177
190
|
|
178
191
|
def description
|
179
192
|
"have an exact height of #{@height}"
|
180
193
|
end
|
194
|
+
|
195
|
+
# RSpec 2 compatibility:
|
196
|
+
alias_method :negative_failure_message, :failure_message_when_negated
|
181
197
|
end
|
182
198
|
|
183
199
|
def have_height(height)
|
@@ -201,13 +217,16 @@ module CarrierWave
|
|
201
217
|
"expected #{@actual.current_path.inspect} to have an exact size of #{@width}, but it was #{@actual_width}."
|
202
218
|
end
|
203
219
|
|
204
|
-
def
|
220
|
+
def failure_message_when_negated
|
205
221
|
"expected #{@actual.current_path.inspect} not to have an exact size of #{@width}, but it did."
|
206
222
|
end
|
207
223
|
|
208
224
|
def description
|
209
225
|
"have an exact width of #{@width}"
|
210
226
|
end
|
227
|
+
|
228
|
+
# RSpec 2 compatibility:
|
229
|
+
alias_method :negative_failure_message, :failure_message_when_negated
|
211
230
|
end
|
212
231
|
|
213
232
|
def have_width(width)
|
@@ -231,13 +250,16 @@ module CarrierWave
|
|
231
250
|
"expected #{@actual.current_path.inspect} to be no wider than #{@width}, but it was #{@actual_width}."
|
232
251
|
end
|
233
252
|
|
234
|
-
def
|
253
|
+
def failure_message_when_negated
|
235
254
|
"expected #{@actual.current_path.inspect} not to be wider than #{@width}, but it is."
|
236
255
|
end
|
237
256
|
|
238
257
|
def description
|
239
258
|
"have a width less than or equal to #{@width}"
|
240
259
|
end
|
260
|
+
|
261
|
+
# RSpec 2 compatibility:
|
262
|
+
alias_method :negative_failure_message, :failure_message_when_negated
|
241
263
|
end
|
242
264
|
|
243
265
|
def be_no_wider_than(width)
|
@@ -261,19 +283,55 @@ module CarrierWave
|
|
261
283
|
"expected #{@actual.current_path.inspect} to be no taller than #{@height}, but it was #{@actual_height}."
|
262
284
|
end
|
263
285
|
|
264
|
-
def
|
286
|
+
def failure_message_when_negated
|
265
287
|
"expected #{@actual.current_path.inspect} not to be taller than #{@height}, but it is."
|
266
288
|
end
|
267
289
|
|
268
290
|
def description
|
269
291
|
"have a height less than or equal to #{@height}"
|
270
292
|
end
|
293
|
+
|
294
|
+
# RSpec 2 compatibility:
|
295
|
+
alias_method :negative_failure_message, :failure_message_when_negated
|
271
296
|
end
|
272
297
|
|
273
298
|
def be_no_taller_than(height)
|
274
299
|
BeNoTallerThan.new(height)
|
275
300
|
end
|
276
301
|
|
302
|
+
class BeFormat # :nodoc:
|
303
|
+
def initialize(expected)
|
304
|
+
@expected = expected
|
305
|
+
end
|
306
|
+
|
307
|
+
def matches?(actual)
|
308
|
+
@actual = actual
|
309
|
+
# Satisfy expectation here. Return false or raise an error if it's not met.
|
310
|
+
image = ImageLoader.load_image(@actual.current_path)
|
311
|
+
@actual_expected = image.format
|
312
|
+
!@expected.nil? && @actual_expected.casecmp(@expected).zero?
|
313
|
+
end
|
314
|
+
|
315
|
+
def failure_message
|
316
|
+
"expected #{@actual.current_path.inspect} to have #{@expected} format, but it was #{@actual_expected}."
|
317
|
+
end
|
318
|
+
|
319
|
+
def failure_message_when_negated
|
320
|
+
"expected #{@actual.current_path.inspect} not to have #{@expected} format, but it did."
|
321
|
+
end
|
322
|
+
|
323
|
+
def description
|
324
|
+
"have #{@expected} format"
|
325
|
+
end
|
326
|
+
|
327
|
+
# RSpec 2 compatibility:
|
328
|
+
alias_method :negative_failure_message, :failure_message_when_negated
|
329
|
+
end
|
330
|
+
|
331
|
+
def be_format(expected)
|
332
|
+
BeFormat.new(expected)
|
333
|
+
end
|
334
|
+
|
277
335
|
class ImageLoader # :nodoc:
|
278
336
|
def self.load_image(filename)
|
279
337
|
if defined? ::MiniMagick
|
@@ -303,6 +361,10 @@ module CarrierWave
|
|
303
361
|
image.rows
|
304
362
|
end
|
305
363
|
|
364
|
+
def format
|
365
|
+
image.format
|
366
|
+
end
|
367
|
+
|
306
368
|
def initialize(filename)
|
307
369
|
@image = ::Magick::Image.read(filename).first
|
308
370
|
end
|
@@ -318,6 +380,10 @@ module CarrierWave
|
|
318
380
|
image[:height]
|
319
381
|
end
|
320
382
|
|
383
|
+
def format
|
384
|
+
image[:format]
|
385
|
+
end
|
386
|
+
|
321
387
|
def initialize(filename)
|
322
388
|
@image = ::MiniMagick::Image.open(filename)
|
323
389
|
end
|
@@ -326,4 +392,3 @@ module CarrierWave
|
|
326
392
|
end # Matchers
|
327
393
|
end # Test
|
328
394
|
end # CarrierWave
|
329
|
-
|