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.
Files changed (159) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +3 -0
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
  4. data/.github/ISSUE_TEMPLATE/custom.md +10 -0
  5. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  6. data/.hound.yml +3 -1055
  7. data/.rubocop.yml +1061 -1
  8. data/.travis.yml +23 -4
  9. data/Appraisals +23 -0
  10. data/CONTRIBUTING.md +4 -5
  11. data/Gemfile +10 -7
  12. data/NEWS +52 -0
  13. data/README.md +58 -46
  14. data/Rakefile +29 -21
  15. data/UPGRADING +3 -3
  16. data/features/basic_integration.feature +4 -0
  17. data/features/migration.feature +10 -51
  18. data/features/step_definitions/attachment_steps.rb +23 -13
  19. data/features/step_definitions/html_steps.rb +5 -5
  20. data/features/step_definitions/rails_steps.rb +29 -9
  21. data/features/step_definitions/s3_steps.rb +3 -3
  22. data/features/step_definitions/web_steps.rb +5 -6
  23. data/features/support/env.rb +4 -4
  24. data/features/support/fakeweb.rb +3 -5
  25. data/features/support/file_helpers.rb +2 -2
  26. data/features/support/paths.rb +4 -4
  27. data/features/support/rails.rb +7 -7
  28. data/features/support/selectors.rb +1 -1
  29. data/gemfiles/4.2.gemfile +7 -4
  30. data/gemfiles/5.0.gemfile +7 -4
  31. data/gemfiles/5.1.gemfile +20 -0
  32. data/gemfiles/5.2.gemfile +20 -0
  33. data/gemfiles/6.0.gemfile +20 -0
  34. data/gemfiles/6.1.gemfile +21 -0
  35. data/gemfiles/7.0.gemfile +21 -0
  36. data/lib/generators/paperclip/paperclip_generator.rb +6 -8
  37. data/lib/paperclip/attachment.rb +103 -105
  38. data/lib/paperclip/attachment_registry.rb +2 -2
  39. data/lib/paperclip/content_type_detector.rb +10 -5
  40. data/lib/paperclip/file_command_content_type_detector.rb +1 -3
  41. data/lib/paperclip/filename_cleaner.rb +0 -1
  42. data/lib/paperclip/geometry.rb +18 -19
  43. data/lib/paperclip/geometry_detector_factory.rb +13 -16
  44. data/lib/paperclip/geometry_parser_factory.rb +5 -5
  45. data/lib/paperclip/glue.rb +3 -3
  46. data/lib/paperclip/has_attached_file.rb +5 -4
  47. data/lib/paperclip/helpers.rb +3 -3
  48. data/lib/paperclip/interpolations.rb +42 -38
  49. data/lib/paperclip/io_adapters/abstract_adapter.rb +16 -14
  50. data/lib/paperclip/io_adapters/attachment_adapter.rb +12 -6
  51. data/lib/paperclip/io_adapters/data_uri_adapter.rb +1 -1
  52. data/lib/paperclip/io_adapters/file_adapter.rb +1 -3
  53. data/lib/paperclip/io_adapters/http_url_proxy_adapter.rb +1 -1
  54. data/lib/paperclip/io_adapters/identity_adapter.rb +1 -2
  55. data/lib/paperclip/io_adapters/registry.rb +1 -1
  56. data/lib/paperclip/io_adapters/stringio_adapter.rb +1 -1
  57. data/lib/paperclip/io_adapters/uploaded_file_adapter.rb +6 -8
  58. data/lib/paperclip/io_adapters/uri_adapter.rb +21 -9
  59. data/lib/paperclip/logger.rb +1 -1
  60. data/lib/paperclip/matchers/have_attached_file_matcher.rb +4 -4
  61. data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +19 -18
  62. data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +4 -4
  63. data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +11 -10
  64. data/lib/paperclip/matchers.rb +4 -4
  65. data/lib/paperclip/media_type_spoof_detector.rb +13 -13
  66. data/lib/paperclip/missing_attachment_styles.rb +11 -6
  67. data/lib/paperclip/processor.rb +13 -6
  68. data/lib/paperclip/processor_helpers.rb +3 -1
  69. data/lib/paperclip/rails_environment.rb +1 -5
  70. data/lib/paperclip/railtie.rb +5 -5
  71. data/lib/paperclip/schema.rb +16 -12
  72. data/lib/paperclip/storage/filesystem.rb +6 -8
  73. data/lib/paperclip/storage/fog.rb +36 -32
  74. data/lib/paperclip/storage/s3.rb +68 -76
  75. data/lib/paperclip/style.rb +3 -6
  76. data/lib/paperclip/tempfile.rb +4 -5
  77. data/lib/paperclip/tempfile_factory.rb +0 -1
  78. data/lib/paperclip/thumbnail.rb +11 -11
  79. data/lib/paperclip/url_generator.rb +5 -5
  80. data/lib/paperclip/validators/attachment_content_type_validator.rb +11 -4
  81. data/lib/paperclip/validators/attachment_file_name_validator.rb +14 -12
  82. data/lib/paperclip/validators/attachment_file_type_ignorance_validator.rb +1 -2
  83. data/lib/paperclip/validators/attachment_presence_validator.rb +3 -5
  84. data/lib/paperclip/validators/attachment_size_validator.rb +28 -11
  85. data/lib/paperclip/validators/media_type_spoof_detection_validator.rb +3 -1
  86. data/lib/paperclip/validators.rb +16 -17
  87. data/lib/paperclip/version.rb +1 -3
  88. data/lib/paperclip.rb +49 -48
  89. data/lib/tasks/paperclip.rake +23 -24
  90. data/paperclip.gemspec +29 -33
  91. data/shoulda_macros/paperclip.rb +16 -16
  92. data/spec/paperclip/attachment_definitions_spec.rb +5 -5
  93. data/spec/paperclip/attachment_processing_spec.rb +22 -23
  94. data/spec/paperclip/attachment_registry_spec.rb +15 -15
  95. data/spec/paperclip/attachment_spec.rb +238 -196
  96. data/spec/paperclip/content_type_detector_spec.rb +18 -12
  97. data/spec/paperclip/file_command_content_type_detector_spec.rb +10 -10
  98. data/spec/paperclip/filename_cleaner_spec.rb +3 -4
  99. data/spec/paperclip/geometry_detector_spec.rb +7 -8
  100. data/spec/paperclip/geometry_parser_spec.rb +31 -31
  101. data/spec/paperclip/geometry_spec.rb +24 -24
  102. data/spec/paperclip/glue_spec.rb +3 -5
  103. data/spec/paperclip/has_attached_file_spec.rb +46 -126
  104. data/spec/paperclip/integration_spec.rb +111 -77
  105. data/spec/paperclip/interpolations_spec.rb +101 -93
  106. data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +41 -13
  107. data/spec/paperclip/io_adapters/attachment_adapter_spec.rb +8 -10
  108. data/spec/paperclip/io_adapters/data_uri_adapter_spec.rb +13 -14
  109. data/spec/paperclip/io_adapters/empty_string_adapter_spec.rb +4 -4
  110. data/spec/paperclip/io_adapters/file_adapter_spec.rb +12 -12
  111. data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +58 -37
  112. data/spec/paperclip/io_adapters/identity_adapter_spec.rb +1 -1
  113. data/spec/paperclip/io_adapters/nil_adapter_spec.rb +2 -2
  114. data/spec/paperclip/io_adapters/registry_spec.rb +4 -4
  115. data/spec/paperclip/io_adapters/stringio_adapter_spec.rb +10 -10
  116. data/spec/paperclip/io_adapters/uploaded_file_adapter_spec.rb +6 -6
  117. data/spec/paperclip/io_adapters/uri_adapter_spec.rb +90 -31
  118. data/spec/paperclip/matchers/have_attached_file_matcher_spec.rb +3 -3
  119. data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +4 -5
  120. data/spec/paperclip/matchers/validate_attachment_presence_matcher_spec.rb +4 -4
  121. data/spec/paperclip/matchers/validate_attachment_size_matcher_spec.rb +4 -4
  122. data/spec/paperclip/media_type_spoof_detector_spec.rb +50 -24
  123. data/spec/paperclip/meta_class_spec.rb +3 -3
  124. data/spec/paperclip/paperclip_missing_attachment_styles_spec.rb +28 -24
  125. data/spec/paperclip/paperclip_spec.rb +15 -11
  126. data/spec/paperclip/plural_cache_spec.rb +8 -8
  127. data/spec/paperclip/processor_helpers_spec.rb +35 -35
  128. data/spec/paperclip/processor_spec.rb +8 -8
  129. data/spec/paperclip/rails_environment_spec.rb +7 -10
  130. data/spec/paperclip/rake_spec.rb +39 -39
  131. data/spec/paperclip/schema_spec.rb +57 -53
  132. data/spec/paperclip/storage/filesystem_spec.rb +29 -6
  133. data/spec/paperclip/storage/fog_spec.rb +122 -82
  134. data/spec/paperclip/storage/s3_live_spec.rb +22 -22
  135. data/spec/paperclip/storage/s3_spec.rb +649 -583
  136. data/spec/paperclip/style_spec.rb +67 -71
  137. data/spec/paperclip/tempfile_factory_spec.rb +5 -5
  138. data/spec/paperclip/thumbnail_spec.rb +68 -67
  139. data/spec/paperclip/url_generator_spec.rb +18 -19
  140. data/spec/paperclip/validators/attachment_content_type_validator_spec.rb +115 -27
  141. data/spec/paperclip/validators/attachment_file_name_validator_spec.rb +105 -16
  142. data/spec/paperclip/validators/attachment_presence_validator_spec.rb +5 -5
  143. data/spec/paperclip/validators/attachment_size_validator_spec.rb +111 -21
  144. data/spec/paperclip/validators/media_type_spoof_detection_validator_spec.rb +9 -13
  145. data/spec/paperclip/validators_spec.rb +61 -46
  146. data/spec/spec_helper.rb +21 -23
  147. data/spec/support/assertions.rb +8 -6
  148. data/spec/support/fake_model.rb +1 -2
  149. data/spec/support/fake_rails.rb +1 -1
  150. data/spec/support/fixtures/aws_s3.yml +13 -0
  151. data/spec/support/fixtures/sample.xlsm +0 -0
  152. data/spec/support/matchers/exist.rb +1 -1
  153. data/spec/support/matchers/have_column.rb +1 -1
  154. data/spec/support/mock_url_generator_builder.rb +2 -3
  155. data/spec/support/model_reconstruction.rb +16 -12
  156. data/spec/support/reporting.rb +1 -1
  157. data/spec/support/test_data.rb +2 -2
  158. metadata +58 -106
  159. data/spec/support/conditional_filter_helper.rb +0 -5
@@ -1,8 +1,7 @@
1
- # encoding: utf-8
2
- require 'uri'
3
- require 'paperclip/url_generator'
4
- require 'active_support/deprecation'
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
- :convert_options => {},
15
- :default_style => :original,
16
- :default_url => "/:attachment/:style/missing.png",
17
- :escape_url => true,
18
- :restricted_characters => /[&$+,\/:;=?@<>\[\]\{\}\|\\\^~%# ]/,
19
- :filename_cleaner => nil,
20
- :hash_data => ":class/:attachment/:id/:style/:updated_at",
21
- :hash_digest => "SHA1",
22
- :interpolator => Paperclip::Interpolations,
23
- :only_process => [],
24
- :path => ":rails_root/public:url",
25
- :preserve_files => false,
26
- :processors => [:thumbnail],
27
- :source_file_options => {},
28
- :storage => :filesystem,
29
- :styles => {},
30
- :url => "/system/:class/:attachment/:id_partition/:style/:filename",
31
- :url_generator => Paperclip::UrlGenerator,
32
- :use_default_time_zone => true,
33
- :use_timestamp => true,
34
- :whiny => Paperclip.options[:whiny] || Paperclip.options[:whiny_thumbnails],
35
- :validate_media_type => true,
36
- :adapter_options => { hash_digest: Digest::MD5 },
37
- :check_validity_before_processing => true
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(:timestamp => options))
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
- :timestamp => @options[:use_timestamp],
155
- :escape => @options[:escape_url]
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(time = 3600, style_name = default_style)
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
- ! @queued_for_write.empty?
179
+ !@queued_for_write.empty?
185
180
  end
186
181
 
187
182
  # Alias to +url+
188
- def to_s style_name = default_style
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
- require 'openssl' unless defined?(OpenSSL)
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
- saved_only_process, @options[:only_process] = @options[:only_process], style_args
342
- saved_preserve_files, @options[:preserve_files] = @options[:preserve_files], true
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[:only_process] = saved_only_process
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 message #:nodoc:
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
- self.extend(storage_module)
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) if all_options.respond_to?(:call)
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
- [ style_options, all_options ].compact.join(" ")
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
- instance.run_paperclip_callbacks(:post_process) do
510
- instance.run_paperclip_callbacks(:"#{name}_post_process") do
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
- post_process_style(:original, styles[:original]) if styles.include?(:original) && process_style?(:original, style_args)
520
- styles.reject{ |name, style| name == :original }.each do |name, style|
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
- begin
527
- raise RuntimeError.new("Style #{name} has no processors defined.") if style.processors.blank?
528
- intermediate_files = []
529
- original = @queued_for_write[:original]
530
-
531
- @queued_for_write[name] = style.processors.
532
- reduce(original) do |file, processor|
533
- file = Paperclip.processor(processor).make(file, style.processor_options, self)
534
- intermediate_files << file unless file == @queued_for_write[:original]
535
- file
536
- end
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 |error, message|
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
- file.unlink if file.respond_to?(:unlink) && file.path.present? && File.exist?(file.path)
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 'singleton'
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
- type_from_mime_magic || type_from_file_command
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 type_from_mime_magic
70
- @type_from_mime_magic ||= File.open(@filepath) do |file|
71
- MimeMagic.by_magic(file).try(:type)
72
- end
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
@@ -21,9 +21,7 @@ module Paperclip
21
21
  SENSIBLE_DEFAULT
22
22
  end
23
23
 
24
- if type.nil? || type.match(/\(.*?\)/)
25
- type = SENSIBLE_DEFAULT
26
- end
24
+ type = SENSIBLE_DEFAULT if type.nil? || type.match(/\(.*?\)/)
27
25
  type.split(/[:;\s]+/)[0]
28
26
  end
29
27
  end
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  module Paperclip
3
2
  class FilenameCleaner
4
3
  def initialize(invalid_character_regex)
@@ -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 dst, crop = false
94
+ def transformation_to(dst, crop = false)
96
95
  if crop
97
- ratio = Geometry.new( dst.width / self.width, dst.height / self.height )
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 = dst.to_s
100
+ scale_geometry = dst.to_s
102
101
  end
103
102
 
104
- [ scale_geometry, crop_geometry ]
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 >= self.width && new_geometry.height >= self.height
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 <= self.width || new_geometry.height <= self.height
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 dst, ratio
135
+ def scaling(dst, ratio)
137
136
  if ratio.horizontal? || ratio.square?
138
- [ "%dx" % dst.width, ratio.width ]
137
+ ["%dx" % dst.width, ratio.width]
139
138
  else
140
- [ "x%d" % dst.height, ratio.height ]
139
+ ["x%d" % dst.height, ratio.height]
141
140
  end
142
141
  end
143
142
 
144
- def cropping dst, ratio, scale
143
+ def cropping(dst, ratio, scale)
145
144
  if ratio.horizontal? || ratio.square?
146
- "%dx%d+%d+%d" % [ dst.width, dst.height, 0, (self.height * scale - dst.height) / 2 ]
145
+ "%dx%d+%d+%d" % [dst.width, dst.height, 0, (height * scale - dst.height) / 2]
147
146
  else
148
- "%dx%d+%d+%d" % [ dst.width, dst.height, (self.width * scale - dst.width) / 2, 0 ]
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 / self.width.to_f , new_geometry.height.to_f / self.height.to_f].min
155
- Paperclip::Geometry.new((self.width * scale).round, (self.height * scale).round)
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
- begin
17
- orientation = Paperclip.options[:use_exif_orientation] ?
18
- "%[exif:orientation]" : "1"
19
- Paperclip.run(
20
- "identify",
21
- "-format '%wx%h,#{orientation}' :file", {
22
- :file => "#{path}[0]"
23
- }, {
24
- :swallow_stderr => true
25
- }
26
- )
27
- rescue Terrapin::ExitStatusError
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
- :height => @height,
12
- :width => @width,
13
- :modifier => @modifier,
14
- :orientation => @orientation
11
+ height: @height,
12
+ width: @width,
13
+ modifier: @modifier,
14
+ orientation: @orientation
15
15
  )
16
16
  end
17
17
  end
@@ -1,6 +1,6 @@
1
- require 'paperclip/callbacks'
2
- require 'paperclip/validators'
3
- require 'paperclip/schema'
1
+ require "paperclip/callbacks"
2
+ require "paperclip/validators"
3
+ require "paperclip/schema"
4
4
 
5
5
  module Paperclip
6
6
  module Glue
@@ -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, attr, value|
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.length > 0
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
- :if => ->(instance){ instance.send(name).dirty? }
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