kt-paperclip 5.4.0 → 7.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/FUNDING.yml +3 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
- data/.github/ISSUE_TEMPLATE/custom.md +10 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- data/.hound.yml +3 -1055
- data/.rubocop.yml +1061 -1
- data/.travis.yml +23 -4
- data/Appraisals +23 -0
- data/CONTRIBUTING.md +4 -5
- data/Gemfile +10 -7
- data/NEWS +52 -0
- data/README.md +58 -46
- data/Rakefile +29 -21
- data/UPGRADING +3 -3
- data/features/basic_integration.feature +4 -0
- data/features/migration.feature +10 -51
- data/features/step_definitions/attachment_steps.rb +23 -13
- data/features/step_definitions/html_steps.rb +5 -5
- data/features/step_definitions/rails_steps.rb +29 -9
- data/features/step_definitions/s3_steps.rb +3 -3
- data/features/step_definitions/web_steps.rb +5 -6
- data/features/support/env.rb +4 -4
- data/features/support/fakeweb.rb +3 -5
- data/features/support/file_helpers.rb +2 -2
- data/features/support/paths.rb +4 -4
- data/features/support/rails.rb +7 -7
- data/features/support/selectors.rb +1 -1
- data/gemfiles/4.2.gemfile +7 -4
- data/gemfiles/5.0.gemfile +7 -4
- data/gemfiles/5.1.gemfile +20 -0
- data/gemfiles/5.2.gemfile +20 -0
- data/gemfiles/6.0.gemfile +20 -0
- data/gemfiles/6.1.gemfile +21 -0
- data/gemfiles/7.0.gemfile +21 -0
- data/lib/generators/paperclip/paperclip_generator.rb +6 -8
- data/lib/paperclip/attachment.rb +103 -105
- data/lib/paperclip/attachment_registry.rb +2 -2
- data/lib/paperclip/content_type_detector.rb +10 -5
- data/lib/paperclip/file_command_content_type_detector.rb +1 -3
- data/lib/paperclip/filename_cleaner.rb +0 -1
- data/lib/paperclip/geometry.rb +18 -19
- data/lib/paperclip/geometry_detector_factory.rb +13 -16
- data/lib/paperclip/geometry_parser_factory.rb +5 -5
- data/lib/paperclip/glue.rb +3 -3
- data/lib/paperclip/has_attached_file.rb +5 -4
- data/lib/paperclip/helpers.rb +3 -3
- data/lib/paperclip/interpolations.rb +42 -38
- data/lib/paperclip/io_adapters/abstract_adapter.rb +16 -14
- data/lib/paperclip/io_adapters/attachment_adapter.rb +12 -6
- data/lib/paperclip/io_adapters/data_uri_adapter.rb +1 -1
- data/lib/paperclip/io_adapters/file_adapter.rb +1 -3
- data/lib/paperclip/io_adapters/http_url_proxy_adapter.rb +1 -1
- data/lib/paperclip/io_adapters/identity_adapter.rb +1 -2
- data/lib/paperclip/io_adapters/registry.rb +1 -1
- data/lib/paperclip/io_adapters/stringio_adapter.rb +1 -1
- data/lib/paperclip/io_adapters/uploaded_file_adapter.rb +6 -8
- data/lib/paperclip/io_adapters/uri_adapter.rb +21 -9
- data/lib/paperclip/logger.rb +1 -1
- data/lib/paperclip/matchers/have_attached_file_matcher.rb +4 -4
- data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +19 -18
- data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +4 -4
- data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +11 -10
- data/lib/paperclip/matchers.rb +4 -4
- data/lib/paperclip/media_type_spoof_detector.rb +13 -13
- data/lib/paperclip/missing_attachment_styles.rb +11 -6
- data/lib/paperclip/processor.rb +13 -6
- data/lib/paperclip/processor_helpers.rb +3 -1
- data/lib/paperclip/rails_environment.rb +1 -5
- data/lib/paperclip/railtie.rb +5 -5
- data/lib/paperclip/schema.rb +16 -12
- data/lib/paperclip/storage/filesystem.rb +6 -8
- data/lib/paperclip/storage/fog.rb +36 -32
- data/lib/paperclip/storage/s3.rb +68 -76
- data/lib/paperclip/style.rb +3 -6
- data/lib/paperclip/tempfile.rb +4 -5
- data/lib/paperclip/tempfile_factory.rb +0 -1
- data/lib/paperclip/thumbnail.rb +11 -11
- data/lib/paperclip/url_generator.rb +5 -5
- data/lib/paperclip/validators/attachment_content_type_validator.rb +11 -4
- data/lib/paperclip/validators/attachment_file_name_validator.rb +14 -12
- data/lib/paperclip/validators/attachment_file_type_ignorance_validator.rb +1 -2
- data/lib/paperclip/validators/attachment_presence_validator.rb +3 -5
- data/lib/paperclip/validators/attachment_size_validator.rb +28 -11
- data/lib/paperclip/validators/media_type_spoof_detection_validator.rb +3 -1
- data/lib/paperclip/validators.rb +16 -17
- data/lib/paperclip/version.rb +1 -3
- data/lib/paperclip.rb +49 -48
- data/lib/tasks/paperclip.rake +23 -24
- data/paperclip.gemspec +29 -33
- data/shoulda_macros/paperclip.rb +16 -16
- data/spec/paperclip/attachment_definitions_spec.rb +5 -5
- data/spec/paperclip/attachment_processing_spec.rb +22 -23
- data/spec/paperclip/attachment_registry_spec.rb +15 -15
- data/spec/paperclip/attachment_spec.rb +238 -196
- data/spec/paperclip/content_type_detector_spec.rb +18 -12
- data/spec/paperclip/file_command_content_type_detector_spec.rb +10 -10
- data/spec/paperclip/filename_cleaner_spec.rb +3 -4
- data/spec/paperclip/geometry_detector_spec.rb +7 -8
- data/spec/paperclip/geometry_parser_spec.rb +31 -31
- data/spec/paperclip/geometry_spec.rb +24 -24
- data/spec/paperclip/glue_spec.rb +3 -5
- data/spec/paperclip/has_attached_file_spec.rb +46 -126
- data/spec/paperclip/integration_spec.rb +111 -77
- data/spec/paperclip/interpolations_spec.rb +101 -93
- data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +41 -13
- data/spec/paperclip/io_adapters/attachment_adapter_spec.rb +8 -10
- data/spec/paperclip/io_adapters/data_uri_adapter_spec.rb +13 -14
- data/spec/paperclip/io_adapters/empty_string_adapter_spec.rb +4 -4
- data/spec/paperclip/io_adapters/file_adapter_spec.rb +12 -12
- data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +58 -37
- data/spec/paperclip/io_adapters/identity_adapter_spec.rb +1 -1
- data/spec/paperclip/io_adapters/nil_adapter_spec.rb +2 -2
- data/spec/paperclip/io_adapters/registry_spec.rb +4 -4
- data/spec/paperclip/io_adapters/stringio_adapter_spec.rb +10 -10
- data/spec/paperclip/io_adapters/uploaded_file_adapter_spec.rb +6 -6
- data/spec/paperclip/io_adapters/uri_adapter_spec.rb +90 -31
- data/spec/paperclip/matchers/have_attached_file_matcher_spec.rb +3 -3
- data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +4 -5
- data/spec/paperclip/matchers/validate_attachment_presence_matcher_spec.rb +4 -4
- data/spec/paperclip/matchers/validate_attachment_size_matcher_spec.rb +4 -4
- data/spec/paperclip/media_type_spoof_detector_spec.rb +50 -24
- data/spec/paperclip/meta_class_spec.rb +3 -3
- data/spec/paperclip/paperclip_missing_attachment_styles_spec.rb +28 -24
- data/spec/paperclip/paperclip_spec.rb +15 -11
- data/spec/paperclip/plural_cache_spec.rb +8 -8
- data/spec/paperclip/processor_helpers_spec.rb +35 -35
- data/spec/paperclip/processor_spec.rb +8 -8
- data/spec/paperclip/rails_environment_spec.rb +7 -10
- data/spec/paperclip/rake_spec.rb +39 -39
- data/spec/paperclip/schema_spec.rb +57 -53
- data/spec/paperclip/storage/filesystem_spec.rb +29 -6
- data/spec/paperclip/storage/fog_spec.rb +122 -82
- data/spec/paperclip/storage/s3_live_spec.rb +22 -22
- data/spec/paperclip/storage/s3_spec.rb +649 -583
- data/spec/paperclip/style_spec.rb +67 -71
- data/spec/paperclip/tempfile_factory_spec.rb +5 -5
- data/spec/paperclip/thumbnail_spec.rb +68 -67
- data/spec/paperclip/url_generator_spec.rb +18 -19
- data/spec/paperclip/validators/attachment_content_type_validator_spec.rb +115 -27
- data/spec/paperclip/validators/attachment_file_name_validator_spec.rb +105 -16
- data/spec/paperclip/validators/attachment_presence_validator_spec.rb +5 -5
- data/spec/paperclip/validators/attachment_size_validator_spec.rb +111 -21
- data/spec/paperclip/validators/media_type_spoof_detection_validator_spec.rb +9 -13
- data/spec/paperclip/validators_spec.rb +61 -46
- data/spec/spec_helper.rb +21 -23
- data/spec/support/assertions.rb +8 -6
- data/spec/support/fake_model.rb +1 -2
- data/spec/support/fake_rails.rb +1 -1
- data/spec/support/fixtures/aws_s3.yml +13 -0
- data/spec/support/fixtures/sample.xlsm +0 -0
- data/spec/support/matchers/exist.rb +1 -1
- data/spec/support/matchers/have_column.rb +1 -1
- data/spec/support/mock_url_generator_builder.rb +2 -3
- data/spec/support/model_reconstruction.rb +16 -12
- data/spec/support/reporting.rb +1 -1
- data/spec/support/test_data.rb +2 -2
- metadata +58 -106
- data/spec/support/conditional_filter_helper.rb +0 -5
data/lib/paperclip/attachment.rb
CHANGED
@@ -1,8 +1,7 @@
|
|
1
|
-
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require 'active_support/core_ext/string/inflections'
|
1
|
+
require "uri"
|
2
|
+
require "paperclip/url_generator"
|
3
|
+
require "active_support/deprecation"
|
4
|
+
require "active_support/core_ext/string/inflections"
|
6
5
|
|
7
6
|
module Paperclip
|
8
7
|
# The Attachment class manages the files for a given attachment. It saves
|
@@ -11,35 +10,35 @@ module Paperclip
|
|
11
10
|
class Attachment
|
12
11
|
def self.default_options
|
13
12
|
@default_options ||= {
|
14
|
-
:
|
15
|
-
|
16
|
-
:
|
17
|
-
:
|
18
|
-
:
|
19
|
-
:
|
20
|
-
:
|
21
|
-
:
|
22
|
-
:
|
23
|
-
:
|
24
|
-
:
|
25
|
-
:
|
26
|
-
:
|
27
|
-
:
|
28
|
-
|
29
|
-
:
|
30
|
-
:
|
31
|
-
:
|
32
|
-
:
|
33
|
-
:
|
34
|
-
:
|
35
|
-
:
|
36
|
-
:
|
37
|
-
:
|
13
|
+
convert_options: {},
|
14
|
+
default_style: :original,
|
15
|
+
default_url: "/:attachment/:style/missing.png",
|
16
|
+
escape_url: true,
|
17
|
+
restricted_characters: /[&$+,\/:;=?@<>\[\]\{\}\|\\\^~%# ]/,
|
18
|
+
filename_cleaner: nil,
|
19
|
+
hash_data: ":class/:attachment/:id/:style/:updated_at",
|
20
|
+
hash_digest: "SHA1",
|
21
|
+
interpolator: Paperclip::Interpolations,
|
22
|
+
only_process: [],
|
23
|
+
path: ":rails_root/public:url",
|
24
|
+
preserve_files: false,
|
25
|
+
processors: [:thumbnail],
|
26
|
+
source_file_options: {},
|
27
|
+
storage: :filesystem,
|
28
|
+
styles: {},
|
29
|
+
url: "/system/:class/:attachment/:id_partition/:style/:filename",
|
30
|
+
url_generator: Paperclip::UrlGenerator,
|
31
|
+
use_default_time_zone: true,
|
32
|
+
use_timestamp: true,
|
33
|
+
whiny: Paperclip.options[:whiny] || Paperclip.options[:whiny_thumbnails],
|
34
|
+
validate_media_type: true,
|
35
|
+
adapter_options: { hash_digest: Digest::MD5 },
|
36
|
+
check_validity_before_processing: true
|
38
37
|
}
|
39
38
|
end
|
40
39
|
|
41
40
|
attr_reader :name, :instance, :default_style, :convert_options, :queued_for_write, :whiny,
|
42
|
-
:options, :interpolator, :source_file_options
|
41
|
+
:options, :interpolator, :source_file_options, :queued_for_delete
|
43
42
|
attr_accessor :post_processing
|
44
43
|
|
45
44
|
# Creates an Attachment object. +name+ is the name of the attachment,
|
@@ -113,8 +112,6 @@ module Paperclip
|
|
113
112
|
post_process_file
|
114
113
|
reset_file_if_original_reprocessed
|
115
114
|
end
|
116
|
-
else
|
117
|
-
nil
|
118
115
|
end
|
119
116
|
end
|
120
117
|
|
@@ -143,7 +140,7 @@ module Paperclip
|
|
143
140
|
|
144
141
|
def url(style_name = default_style, options = {})
|
145
142
|
if options == true || options == false # Backwards compatibility.
|
146
|
-
@url_generator.for(style_name, default_options.merge(:
|
143
|
+
@url_generator.for(style_name, default_options.merge(timestamp: options))
|
147
144
|
else
|
148
145
|
@url_generator.for(style_name, default_options.merge(options))
|
149
146
|
end
|
@@ -151,15 +148,15 @@ module Paperclip
|
|
151
148
|
|
152
149
|
def default_options
|
153
150
|
{
|
154
|
-
:
|
155
|
-
:
|
151
|
+
timestamp: @options[:use_timestamp],
|
152
|
+
escape: @options[:escape_url]
|
156
153
|
}
|
157
154
|
end
|
158
155
|
|
159
156
|
# Alias to +url+ that allows using the expiring_url method provided by the cloud
|
160
157
|
# storage implementations, but keep using filesystem storage for development and
|
161
158
|
# testing.
|
162
|
-
def expiring_url(
|
159
|
+
def expiring_url(_time = 3600, style_name = default_style)
|
163
160
|
url(style_name)
|
164
161
|
end
|
165
162
|
|
@@ -174,18 +171,16 @@ module Paperclip
|
|
174
171
|
|
175
172
|
# :nodoc:
|
176
173
|
def staged_path(style_name = default_style)
|
177
|
-
if staged?
|
178
|
-
@queued_for_write[style_name].path
|
179
|
-
end
|
174
|
+
@queued_for_write[style_name].path if staged?
|
180
175
|
end
|
181
176
|
|
182
177
|
# :nodoc:
|
183
178
|
def staged?
|
184
|
-
|
179
|
+
!@queued_for_write.empty?
|
185
180
|
end
|
186
181
|
|
187
182
|
# Alias to +url+
|
188
|
-
def to_s
|
183
|
+
def to_s(style_name = default_style)
|
189
184
|
url(style_name)
|
190
185
|
end
|
191
186
|
|
@@ -241,9 +236,7 @@ module Paperclip
|
|
241
236
|
def save
|
242
237
|
flush_deletes unless @options[:keep_old_files]
|
243
238
|
process = only_process
|
244
|
-
if process.any? && !process.include?(:original)
|
245
|
-
@queued_for_write.except!(:original)
|
246
|
-
end
|
239
|
+
@queued_for_write.except!(:original) if process.any? && !process.include?(:original)
|
247
240
|
flush_writes
|
248
241
|
@dirty = false
|
249
242
|
true
|
@@ -325,7 +318,8 @@ module Paperclip
|
|
325
318
|
# publicly viewable attachment.
|
326
319
|
def hash_key(style_name = default_style)
|
327
320
|
raise ArgumentError, "Unable to generate hash without :hash_secret" unless @options[:hash_secret]
|
328
|
-
|
321
|
+
|
322
|
+
require "openssl" unless defined?(OpenSSL)
|
329
323
|
data = interpolate(@options[:hash_data], style_name)
|
330
324
|
OpenSSL::HMAC.hexdigest(OpenSSL::Digest.const_get(@options[:hash_digest]).new, @options[:hash_secret], data)
|
331
325
|
end
|
@@ -338,8 +332,15 @@ module Paperclip
|
|
338
332
|
# inconsistencies in timing of S3 commands. It's possible that calling
|
339
333
|
# #reprocess! will lose data if the files are not kept.
|
340
334
|
def reprocess!(*style_args)
|
341
|
-
|
342
|
-
|
335
|
+
saved_flags = @options.slice(
|
336
|
+
:only_process,
|
337
|
+
:preserve_files,
|
338
|
+
:check_validity_before_processing
|
339
|
+
)
|
340
|
+
@options[:only_process] = style_args
|
341
|
+
@options[:preserve_files] = true
|
342
|
+
@options[:check_validity_before_processing] = false
|
343
|
+
|
343
344
|
begin
|
344
345
|
assign(self)
|
345
346
|
save
|
@@ -348,8 +349,7 @@ module Paperclip
|
|
348
349
|
warn "#{e} - skipping file."
|
349
350
|
false
|
350
351
|
ensure
|
351
|
-
@options
|
352
|
-
@options[:preserve_files] = saved_preserve_files
|
352
|
+
@options.merge!(saved_flags)
|
353
353
|
end
|
354
354
|
end
|
355
355
|
|
@@ -375,18 +375,14 @@ module Paperclip
|
|
375
375
|
# "avatar_file_name" field (assuming the attachment is called avatar).
|
376
376
|
def instance_write(attr, value)
|
377
377
|
setter = :"#{@name_string}_#{attr}="
|
378
|
-
if instance.respond_to?(setter)
|
379
|
-
instance.send(setter, value)
|
380
|
-
end
|
378
|
+
instance.send(setter, value) if instance.respond_to?(setter)
|
381
379
|
end
|
382
380
|
|
383
381
|
# Reads the attachment-specific attribute on the instance. See instance_write
|
384
382
|
# for more details.
|
385
383
|
def instance_read(attr)
|
386
384
|
getter = :"#{@name_string}_#{attr}"
|
387
|
-
if instance.respond_to?(getter)
|
388
|
-
instance.send(getter)
|
389
|
-
end
|
385
|
+
instance.send(getter) if instance.respond_to?(getter)
|
390
386
|
end
|
391
387
|
|
392
388
|
private
|
@@ -404,9 +400,7 @@ module Paperclip
|
|
404
400
|
end
|
405
401
|
|
406
402
|
def ensure_required_validations!
|
407
|
-
if missing_required_validator?
|
408
|
-
raise Paperclip::Errors::MissingRequiredValidatorError
|
409
|
-
end
|
403
|
+
raise Paperclip::Errors::MissingRequiredValidatorError if missing_required_validator?
|
410
404
|
end
|
411
405
|
|
412
406
|
def ensure_required_accessors! #:nodoc:
|
@@ -417,7 +411,7 @@ module Paperclip
|
|
417
411
|
end
|
418
412
|
end
|
419
413
|
|
420
|
-
def log
|
414
|
+
def log(message) #:nodoc:
|
421
415
|
Paperclip.log(message)
|
422
416
|
end
|
423
417
|
|
@@ -428,7 +422,7 @@ module Paperclip
|
|
428
422
|
rescue NameError
|
429
423
|
raise Errors::StorageMethodNotFound, "Cannot load storage module '#{storage_class_name}'"
|
430
424
|
end
|
431
|
-
|
425
|
+
extend(storage_module)
|
432
426
|
end
|
433
427
|
|
434
428
|
def assign_attributes
|
@@ -445,15 +439,11 @@ module Paperclip
|
|
445
439
|
end
|
446
440
|
|
447
441
|
def assign_fingerprint
|
448
|
-
if instance_respond_to?(:fingerprint)
|
449
|
-
instance_write(:fingerprint, yield)
|
450
|
-
end
|
442
|
+
instance_write(:fingerprint, yield) if instance_respond_to?(:fingerprint)
|
451
443
|
end
|
452
444
|
|
453
445
|
def assign_timestamps
|
454
|
-
if has_enabled_but_unset_created_at?
|
455
|
-
instance_write(:created_at, Time.now)
|
456
|
-
end
|
446
|
+
instance_write(:created_at, Time.now) if has_enabled_but_unset_created_at?
|
457
447
|
|
458
448
|
instance_write(:updated_at, Time.now)
|
459
449
|
end
|
@@ -461,9 +451,7 @@ module Paperclip
|
|
461
451
|
def post_process_file
|
462
452
|
dirty!
|
463
453
|
|
464
|
-
if post_processing
|
465
|
-
post_process(*only_process)
|
466
|
-
end
|
454
|
+
post_process(*only_process) if post_processing
|
467
455
|
end
|
468
456
|
|
469
457
|
def dirty!
|
@@ -477,9 +465,7 @@ module Paperclip
|
|
477
465
|
end
|
478
466
|
|
479
467
|
def reset_updater
|
480
|
-
if instance.respond_to?(updater)
|
481
|
-
instance.send(updater)
|
482
|
-
end
|
468
|
+
instance.send(updater) if instance.respond_to?(updater)
|
483
469
|
end
|
484
470
|
|
485
471
|
def updater
|
@@ -496,56 +482,63 @@ module Paperclip
|
|
496
482
|
|
497
483
|
def process_options(options_type, style) #:nodoc:
|
498
484
|
all_options = @options[options_type][:all]
|
499
|
-
all_options = all_options.call(instance)
|
485
|
+
all_options = all_options.call(instance) if all_options.respond_to?(:call)
|
500
486
|
style_options = @options[options_type][style]
|
501
487
|
style_options = style_options.call(instance) if style_options.respond_to?(:call)
|
502
488
|
|
503
|
-
[
|
489
|
+
[style_options, all_options].compact.join(" ")
|
504
490
|
end
|
505
491
|
|
506
492
|
def post_process(*style_args) #:nodoc:
|
507
493
|
return if @queued_for_write[:original].nil?
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
if !@options[:check_validity_before_processing] || !instance.errors.any?
|
494
|
+
if !@options[:check_validity_before_processing] || check_validity?
|
495
|
+
instance.run_paperclip_callbacks(:post_process) do
|
496
|
+
instance.run_paperclip_callbacks(:"#{name}_post_process") do
|
512
497
|
post_process_styles(*style_args)
|
513
498
|
end
|
514
499
|
end
|
515
500
|
end
|
516
501
|
end
|
517
502
|
|
503
|
+
def check_validity?
|
504
|
+
instance.run_paperclip_callbacks(:"#{name}_validate")
|
505
|
+
instance.errors.none?
|
506
|
+
end
|
507
|
+
|
518
508
|
def post_process_styles(*style_args) #:nodoc:
|
519
|
-
|
520
|
-
|
509
|
+
if styles.include?(:original) && process_style?(:original, style_args)
|
510
|
+
post_process_style(:original, styles[:original])
|
511
|
+
end
|
512
|
+
styles.reject { |name, _style| name == :original }.each do |name, style|
|
521
513
|
post_process_style(name, style) if process_style?(name, style_args)
|
522
514
|
end
|
523
515
|
end
|
524
516
|
|
525
517
|
def post_process_style(name, style) #:nodoc:
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
unadapted_file = @queued_for_write[name]
|
539
|
-
@queued_for_write[name] = Paperclip.io_adapters.
|
540
|
-
for(@queued_for_write[name], @options[:adapter_options])
|
541
|
-
unadapted_file.close if unadapted_file.respond_to?(:close)
|
542
|
-
@queued_for_write[name]
|
543
|
-
rescue Paperclip::Errors::NotIdentifiedByImageMagickError => e
|
544
|
-
log("An error was received while processing: #{e.inspect}")
|
545
|
-
(@errors[:processing] ||= []) << e.message if @options[:whiny]
|
546
|
-
ensure
|
547
|
-
unlink_files(intermediate_files)
|
518
|
+
raise "Style #{name} has no processors defined." if style.processors.blank?
|
519
|
+
|
520
|
+
intermediate_files = []
|
521
|
+
original = @queued_for_write[:original]
|
522
|
+
|
523
|
+
@queued_for_write[name] = style.processors.
|
524
|
+
inject(original) do |file, processor|
|
525
|
+
file = Paperclip.processor(processor).make(file, style.processor_options, self)
|
526
|
+
intermediate_files << file unless file == @queued_for_write[:original]
|
527
|
+
# if we're processing the original, close + unlink the source tempfile
|
528
|
+
@queued_for_write[:original].close(true) if name == :original
|
529
|
+
file
|
548
530
|
end
|
531
|
+
|
532
|
+
unadapted_file = @queued_for_write[name]
|
533
|
+
@queued_for_write[name] = Paperclip.io_adapters.
|
534
|
+
for(@queued_for_write[name], @options[:adapter_options])
|
535
|
+
unadapted_file.close if unadapted_file.respond_to?(:close)
|
536
|
+
@queued_for_write[name]
|
537
|
+
rescue Paperclip::Errors::NotIdentifiedByImageMagickError => e
|
538
|
+
log("An error was received while processing: #{e.inspect}")
|
539
|
+
(@errors[:processing] ||= []) << e.message if @options[:whiny]
|
540
|
+
ensure
|
541
|
+
unlink_files(intermediate_files)
|
549
542
|
end
|
550
543
|
|
551
544
|
def process_style?(style_name, style_args) #:nodoc:
|
@@ -564,6 +557,7 @@ module Paperclip
|
|
564
557
|
|
565
558
|
def queue_all_for_delete #:nodoc:
|
566
559
|
return if !file?
|
560
|
+
|
567
561
|
unless @options[:preserve_files]
|
568
562
|
@queued_for_delete += [:original, *styles.keys].uniq.map do |style|
|
569
563
|
path(style) if exists?(style)
|
@@ -578,8 +572,8 @@ module Paperclip
|
|
578
572
|
end
|
579
573
|
|
580
574
|
def flush_errors #:nodoc:
|
581
|
-
@errors.each do |
|
582
|
-
[message].flatten.each {|m| instance.errors.add(name, m) }
|
575
|
+
@errors.each do |_error, message|
|
576
|
+
[message].flatten.each { |m| instance.errors.add(name, m) }
|
583
577
|
end
|
584
578
|
end
|
585
579
|
|
@@ -591,7 +585,11 @@ module Paperclip
|
|
591
585
|
def unlink_files(files)
|
592
586
|
Array(files).each do |file|
|
593
587
|
file.close unless file.closed?
|
594
|
-
|
588
|
+
|
589
|
+
begin
|
590
|
+
file.unlink if file.respond_to?(:unlink)
|
591
|
+
rescue Errno::ENOENT
|
592
|
+
end
|
595
593
|
end
|
596
594
|
end
|
597
595
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "singleton"
|
2
2
|
|
3
3
|
module Paperclip
|
4
4
|
class AttachmentRegistry
|
@@ -35,7 +35,7 @@ module Paperclip
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def clear
|
38
|
-
@attachments = Hash.new { |h,k| h[k] = {} }
|
38
|
+
@attachments = Hash.new { |h, k| h[k] = {} }
|
39
39
|
end
|
40
40
|
|
41
41
|
def names_for(klass)
|
@@ -60,16 +60,21 @@ module Paperclip
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def type_from_file_contents
|
63
|
-
|
63
|
+
type_from_marcel || type_from_file_command
|
64
64
|
rescue Errno::ENOENT => e
|
65
65
|
Paperclip.log("Error while determining content type: #{e}")
|
66
66
|
SENSIBLE_DEFAULT
|
67
67
|
end
|
68
68
|
|
69
|
-
def
|
70
|
-
@
|
71
|
-
|
72
|
-
|
69
|
+
def type_from_marcel
|
70
|
+
return @type_from_marcel if defined? @type_from_marcel
|
71
|
+
|
72
|
+
@type_from_marcel = Marcel::MimeType.for Pathname.new(@filepath),
|
73
|
+
name: @filepath
|
74
|
+
# Marcel::MineType returns 'application/octet-stream' if it can't find
|
75
|
+
# a valid type.
|
76
|
+
@type_from_marcel = nil if @type_from_marcel == SENSIBLE_DEFAULT
|
77
|
+
@type_from_marcel
|
73
78
|
end
|
74
79
|
|
75
80
|
def type_from_file_command
|
data/lib/paperclip/geometry.rb
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
module Paperclip
|
2
|
-
|
3
2
|
# Defines the geometry of an image.
|
4
3
|
class Geometry
|
5
4
|
attr_accessor :height, :width, :modifier
|
6
5
|
|
7
|
-
EXIF_ROTATED_ORIENTATION_VALUES = [5, 6, 7, 8]
|
6
|
+
EXIF_ROTATED_ORIENTATION_VALUES = [5, 6, 7, 8].freeze
|
8
7
|
|
9
8
|
# Gives a Geometry representing the given height and width
|
10
9
|
def initialize(width = nil, height = nil, modifier = nil)
|
@@ -92,16 +91,16 @@ module Paperclip
|
|
92
91
|
# destination Geometry would be completely filled by the source image, and any
|
93
92
|
# overhanging image would be cropped. Useful for square thumbnail images. The cropping
|
94
93
|
# is weighted at the center of the Geometry.
|
95
|
-
def transformation_to
|
94
|
+
def transformation_to(dst, crop = false)
|
96
95
|
if crop
|
97
|
-
ratio = Geometry.new(
|
96
|
+
ratio = Geometry.new(dst.width / width, dst.height / height)
|
98
97
|
scale_geometry, scale = scaling(dst, ratio)
|
99
98
|
crop_geometry = cropping(dst, ratio, scale)
|
100
99
|
else
|
101
|
-
scale_geometry
|
100
|
+
scale_geometry = dst.to_s
|
102
101
|
end
|
103
102
|
|
104
|
-
[
|
103
|
+
[scale_geometry, crop_geometry]
|
105
104
|
end
|
106
105
|
|
107
106
|
# resize to a new geometry
|
@@ -112,16 +111,16 @@ module Paperclip
|
|
112
111
|
def resize_to(geometry)
|
113
112
|
new_geometry = Paperclip::Geometry.parse geometry
|
114
113
|
case new_geometry.modifier
|
115
|
-
when
|
114
|
+
when "!", "#"
|
116
115
|
new_geometry
|
117
|
-
when
|
118
|
-
if new_geometry.width >=
|
116
|
+
when ">"
|
117
|
+
if new_geometry.width >= width && new_geometry.height >= height
|
119
118
|
self
|
120
119
|
else
|
121
120
|
scale_to new_geometry
|
122
121
|
end
|
123
|
-
when
|
124
|
-
if new_geometry.width <=
|
122
|
+
when "<"
|
123
|
+
if new_geometry.width <= width || new_geometry.height <= height
|
125
124
|
self
|
126
125
|
else
|
127
126
|
scale_to new_geometry
|
@@ -133,26 +132,26 @@ module Paperclip
|
|
133
132
|
|
134
133
|
private
|
135
134
|
|
136
|
-
def scaling
|
135
|
+
def scaling(dst, ratio)
|
137
136
|
if ratio.horizontal? || ratio.square?
|
138
|
-
[
|
137
|
+
["%dx" % dst.width, ratio.width]
|
139
138
|
else
|
140
|
-
[
|
139
|
+
["x%d" % dst.height, ratio.height]
|
141
140
|
end
|
142
141
|
end
|
143
142
|
|
144
|
-
def cropping
|
143
|
+
def cropping(dst, ratio, scale)
|
145
144
|
if ratio.horizontal? || ratio.square?
|
146
|
-
"%dx%d+%d+%d" % [
|
145
|
+
"%dx%d+%d+%d" % [dst.width, dst.height, 0, (height * scale - dst.height) / 2]
|
147
146
|
else
|
148
|
-
"%dx%d+%d+%d" % [
|
147
|
+
"%dx%d+%d+%d" % [dst.width, dst.height, (width * scale - dst.width) / 2, 0]
|
149
148
|
end
|
150
149
|
end
|
151
150
|
|
152
151
|
# scale to the requested geometry and preserve the aspect ratio
|
153
152
|
def scale_to(new_geometry)
|
154
|
-
scale = [new_geometry.width.to_f /
|
155
|
-
Paperclip::Geometry.new((
|
153
|
+
scale = [new_geometry.width.to_f / width.to_f, new_geometry.height.to_f / height.to_f].min
|
154
|
+
Paperclip::Geometry.new((width * scale).round, (height * scale).round)
|
156
155
|
end
|
157
156
|
end
|
158
157
|
end
|
@@ -13,22 +13,19 @@ module Paperclip
|
|
13
13
|
private
|
14
14
|
|
15
15
|
def geometry_string
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
Paperclip.
|
20
|
-
|
21
|
-
"
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
rescue Terrapin::CommandNotFoundError => e
|
30
|
-
raise_because_imagemagick_missing
|
31
|
-
end
|
16
|
+
orientation = Paperclip.options[:use_exif_orientation] ?
|
17
|
+
"%[exif:orientation]" : "1"
|
18
|
+
Paperclip.run(
|
19
|
+
Paperclip.options[:is_windows] ? "magick identify" : "identify",
|
20
|
+
"-format '%wx%h,#{orientation}' :file", {
|
21
|
+
file: "#{path}[0]"
|
22
|
+
},
|
23
|
+
swallow_stderr: true
|
24
|
+
)
|
25
|
+
rescue Terrapin::ExitStatusError
|
26
|
+
""
|
27
|
+
rescue Terrapin::CommandNotFoundError => e
|
28
|
+
raise_because_imagemagick_missing
|
32
29
|
end
|
33
30
|
|
34
31
|
def path
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Paperclip
|
2
2
|
class GeometryParser
|
3
|
-
FORMAT = /\b(\d*)x?(\d*)\b(?:,(\d?))?(\@\>|\>\@|[\>\<\#\@\%^!])?/i
|
3
|
+
FORMAT = /\b(\d*)x?(\d*)\b(?:,(\d?))?(\@\>|\>\@|[\>\<\#\@\%^!])?/i.freeze
|
4
4
|
def initialize(string)
|
5
5
|
@string = string
|
6
6
|
end
|
@@ -8,10 +8,10 @@ module Paperclip
|
|
8
8
|
def make
|
9
9
|
if match
|
10
10
|
Geometry.new(
|
11
|
-
:
|
12
|
-
:
|
13
|
-
:
|
14
|
-
:
|
11
|
+
height: @height,
|
12
|
+
width: @width,
|
13
|
+
modifier: @modifier,
|
14
|
+
orientation: @orientation
|
15
15
|
)
|
16
16
|
end
|
17
17
|
end
|
data/lib/paperclip/glue.rb
CHANGED
@@ -24,7 +24,7 @@ module Paperclip
|
|
24
24
|
private
|
25
25
|
|
26
26
|
def define_flush_errors
|
27
|
-
@klass.send(:validates_each, @name) do |record,
|
27
|
+
@klass.send(:validates_each, @name) do |record, _attr, _value|
|
28
28
|
attachment = record.send(@name)
|
29
29
|
attachment.send(:flush_errors)
|
30
30
|
end
|
@@ -48,7 +48,7 @@ module Paperclip
|
|
48
48
|
instance_variable_set(ivar, attachment)
|
49
49
|
end
|
50
50
|
|
51
|
-
if args.
|
51
|
+
if !args.empty?
|
52
52
|
attachment.to_s(args.first)
|
53
53
|
else
|
54
54
|
attachment
|
@@ -83,7 +83,7 @@ module Paperclip
|
|
83
83
|
if options[:validate_media_type] != false
|
84
84
|
name = @name
|
85
85
|
@klass.validates_media_type_spoof_detection name,
|
86
|
-
|
86
|
+
if: ->(instance) { instance.send(name).dirty? }
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
@@ -103,7 +103,8 @@ module Paperclip
|
|
103
103
|
def add_paperclip_callbacks
|
104
104
|
@klass.send(
|
105
105
|
:define_paperclip_callbacks,
|
106
|
-
:post_process, :"#{@name}_post_process"
|
106
|
+
:post_process, :"#{@name}_post_process", :"#{@name}_validate"
|
107
|
+
)
|
107
108
|
end
|
108
109
|
|
109
110
|
module ClassMethods
|