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
@@ -3,8 +3,8 @@ module Paperclip
3
3
  # Amazon's S3 file hosting service is a scalable, easy place to store files for
4
4
  # distribution. You can find out more about it at http://aws.amazon.com/s3
5
5
  #
6
- # To use Paperclip with S3, include the +aws-sdk+ gem in your Gemfile:
7
- # gem 'aws-sdk'
6
+ # To use Paperclip with S3, include the +aws-sdk-s3+ gem in your Gemfile:
7
+ # gem 'aws-sdk-s3'
8
8
  # There are a few S3-specific options for has_attached_file:
9
9
  # * +s3_credentials+: Takes a path, a File, a Hash or a Proc. The path (or File) must point
10
10
  # to a YAML file containing the +access_key_id+ and +secret_access_key+ that Amazon
@@ -96,7 +96,7 @@ module Paperclip
96
96
  # separate parts of your file name.
97
97
  # * +s3_host_name+: If you are using your bucket in Tokyo region
98
98
  # etc, write host_name (e.g., 's3-ap-northeast-1.amazonaws.com').
99
- # * +s3_region+: For aws-sdk v2, s3_region is required.
99
+ # * +s3_region+: For aws-sdk-s3, s3_region is required.
100
100
  # * +s3_metadata+: These key/value pairs will be stored with the
101
101
  # object. This option works by prefixing each key with
102
102
  # "x-amz-meta-" before sending it as a header on the object
@@ -118,25 +118,21 @@ module Paperclip
118
118
  # :s3_storage_class => :REDUCED_REDUNDANCY
119
119
  #
120
120
  # Other storage classes, such as <tt>:STANDARD_IA</tt>, are also available—see the
121
- # documentation for the <tt>aws-sdk</tt> gem for the full list.
121
+ # documentation for the <tt>aws-sdk-s3</tt> gem for the full list.
122
122
 
123
123
  module S3
124
- def self.extended base
124
+ def self.extended(base)
125
125
  begin
126
- require 'aws-sdk'
126
+ require "aws-sdk-s3"
127
127
  rescue LoadError => e
128
- e.message << " (You may need to install the aws-sdk gem)"
128
+ e.message << " (You may need to install the aws-sdk-s3 gem)"
129
129
  raise e
130
130
  end
131
- if Gem::Version.new(Aws::VERSION) >= Gem::Version.new(2) &&
132
- Gem::Version.new(Aws::VERSION) <= Gem::Version.new("2.0.33")
133
- raise LoadError, "paperclip does not support aws-sdk versions 2.0.0 - 2.0.33. Please upgrade aws-sdk to a newer version."
134
- end
135
131
 
136
132
  base.instance_eval do
137
- @s3_options = @options[:s3_options] || {}
133
+ @s3_options = @options[:s3_options] || {}
138
134
  @s3_permissions = set_permissions(@options[:s3_permissions])
139
- @s3_protocol = @options[:s3_protocol] || "".freeze
135
+ @s3_protocol = @options[:s3_protocol] || ""
140
136
  @s3_metadata = @options[:s3_metadata] || {}
141
137
  @s3_headers = {}
142
138
  merge_s3_headers(@options[:s3_headers], @s3_headers, @s3_metadata)
@@ -144,47 +140,46 @@ module Paperclip
144
140
  @s3_storage_class = set_storage_class(@options[:s3_storage_class])
145
141
 
146
142
  @s3_server_side_encryption = "AES256"
147
- if @options[:s3_server_side_encryption].blank?
148
- @s3_server_side_encryption = false
149
- end
150
- if @s3_server_side_encryption
151
- @s3_server_side_encryption = @options[:s3_server_side_encryption]
152
- end
143
+ @s3_server_side_encryption = false if @options[:s3_server_side_encryption].blank?
144
+ @s3_server_side_encryption = @options[:s3_server_side_encryption] if @s3_server_side_encryption
153
145
 
154
- unless @options[:url].to_s.match(/\A:s3.*url\z/) || @options[:url] == ":asset_host".freeze
155
- @options[:path] = path_option.gsub(/:url/, @options[:url]).sub(/\A:rails_root\/public\/system/, "".freeze)
156
- @options[:url] = ":s3_path_url".freeze
146
+ unless @options[:url].to_s.match(/\A:s3.*url\z/) || @options[:url] == ":asset_host"
147
+ @options[:path] = path_option.gsub(/:url/, @options[:url]).sub(/\A:rails_root\/public\/system/, "")
148
+ @options[:url] = ":s3_path_url"
157
149
  end
158
150
  @options[:url] = @options[:url].inspect if @options[:url].is_a?(Symbol)
159
151
 
160
152
  @http_proxy = @options[:http_proxy] || nil
161
153
 
162
- if @options.has_key?(:use_accelerate_endpoint) &&
163
- Gem::Version.new(Aws::VERSION) < Gem::Version.new("2.3.0")
164
- raise LoadError, ":use_accelerate_endpoint is only available from aws-sdk version 2.3.0. Please upgrade aws-sdk to a newer version."
165
- end
166
-
167
154
  @use_accelerate_endpoint = @options[:use_accelerate_endpoint]
168
155
  end
169
156
 
170
- Paperclip.interpolates(:s3_alias_url) do |attachment, style|
171
- protocol = attachment.s3_protocol(style, true)
172
- host = attachment.s3_host_alias
173
- path = attachment.path(style).
174
- split("/")[attachment.s3_prefixes_in_alias..-1].
175
- join("/").
176
- sub(%r{\A/}, "".freeze)
177
- "#{protocol}//#{host}/#{path}"
178
- end unless Paperclip::Interpolations.respond_to? :s3_alias_url
179
- Paperclip.interpolates(:s3_path_url) do |attachment, style|
180
- "#{attachment.s3_protocol(style, true)}//#{attachment.s3_host_name}/#{attachment.bucket_name}/#{attachment.path(style).sub(%r{\A/}, "".freeze)}"
181
- end unless Paperclip::Interpolations.respond_to? :s3_path_url
182
- Paperclip.interpolates(:s3_domain_url) do |attachment, style|
183
- "#{attachment.s3_protocol(style, true)}//#{attachment.bucket_name}.#{attachment.s3_host_name}/#{attachment.path(style).sub(%r{\A/}, "".freeze)}"
184
- end unless Paperclip::Interpolations.respond_to? :s3_domain_url
185
- Paperclip.interpolates(:asset_host) do |attachment, style|
186
- "#{attachment.path(style).sub(%r{\A/}, "".freeze)}"
187
- end unless Paperclip::Interpolations.respond_to? :asset_host
157
+ unless Paperclip::Interpolations.respond_to? :s3_alias_url
158
+ Paperclip.interpolates(:s3_alias_url) do |attachment, style|
159
+ protocol = attachment.s3_protocol(style, true)
160
+ host = attachment.s3_host_alias
161
+ path = attachment.path(style).
162
+ split("/")[attachment.s3_prefixes_in_alias..-1].
163
+ join("/").
164
+ sub(%r{\A/}, "")
165
+ "#{protocol}//#{host}/#{path}"
166
+ end
167
+ end
168
+ unless Paperclip::Interpolations.respond_to? :s3_path_url
169
+ Paperclip.interpolates(:s3_path_url) do |attachment, style|
170
+ "#{attachment.s3_protocol(style, true)}//#{attachment.s3_host_name}/#{attachment.bucket_name}/#{attachment.path(style).sub(%r{\A/}, '')}"
171
+ end
172
+ end
173
+ unless Paperclip::Interpolations.respond_to? :s3_domain_url
174
+ Paperclip.interpolates(:s3_domain_url) do |attachment, style|
175
+ "#{attachment.s3_protocol(style, true)}//#{attachment.bucket_name}.#{attachment.s3_host_name}/#{attachment.path(style).sub(%r{\A/}, '')}"
176
+ end
177
+ end
178
+ unless Paperclip::Interpolations.respond_to? :asset_host
179
+ Paperclip.interpolates(:asset_host) do |attachment, style|
180
+ attachment.path(style).sub(%r{\A/}, "").to_s
181
+ end
182
+ end
188
183
  end
189
184
 
190
185
  def expiring_url(time = 3600, style_name = default_style)
@@ -192,7 +187,7 @@ module Paperclip
192
187
  base_options = { expires_in: time }
193
188
  s3_object(style_name).presigned_url(
194
189
  :get,
195
- base_options.merge(s3_url_options),
190
+ base_options.merge(s3_url_options)
196
191
  ).to_s
197
192
  else
198
193
  url(style_name)
@@ -207,7 +202,7 @@ module Paperclip
207
202
  host_name = @options[:s3_host_name]
208
203
  host_name = host_name.call(self) if host_name.is_a?(Proc)
209
204
 
210
- host_name || s3_credentials[:s3_host_name] || "s3.amazonaws.com".freeze
205
+ host_name || s3_credentials[:s3_host_name] || "s3.amazonaws.com"
211
206
  end
212
207
 
213
208
  def s3_region
@@ -236,7 +231,7 @@ module Paperclip
236
231
  def bucket_name
237
232
  @bucket = @options[:bucket] || s3_credentials[:bucket]
238
233
  @bucket = @bucket.call(self) if @bucket.respond_to?(:call)
239
- @bucket or raise ArgumentError, "missing required :bucket option"
234
+ @bucket || raise(ArgumentError, "missing required :bucket option")
240
235
  end
241
236
 
242
237
  def s3_interface
@@ -245,7 +240,7 @@ module Paperclip
245
240
 
246
241
  if using_http_proxy?
247
242
 
248
- proxy_opts = { :host => http_proxy_host }
243
+ proxy_opts = { host: http_proxy_host }
249
244
  proxy_opts[:port] = http_proxy_port if http_proxy_port
250
245
  if http_proxy_user
251
246
  userinfo = http_proxy_user.to_s
@@ -275,10 +270,10 @@ module Paperclip
275
270
  end
276
271
 
277
272
  def style_name_as_path(style_name)
278
- path(style_name).sub(%r{\A/},'')
273
+ path(style_name).sub(%r{\A/}, "")
279
274
  end
280
275
 
281
- def s3_object style_name = default_style
276
+ def s3_object(style_name = default_style)
282
277
  s3_bucket.object style_name_as_path(style_name)
283
278
  end
284
279
 
@@ -306,17 +301,17 @@ module Paperclip
306
301
  using_http_proxy? ? @http_proxy[:password] : nil
307
302
  end
308
303
 
309
- def set_permissions permissions
310
- permissions = { :default => permissions } unless permissions.respond_to?(:merge)
311
- permissions.merge :default => (permissions[:default] || :"public-read")
304
+ def set_permissions(permissions)
305
+ permissions = { default: permissions } unless permissions.respond_to?(:merge)
306
+ permissions.merge default: (permissions[:default] || :"public-read")
312
307
  end
313
308
 
314
309
  def set_storage_class(storage_class)
315
- storage_class = {:default => storage_class} unless storage_class.respond_to?(:merge)
310
+ storage_class = { default: storage_class } unless storage_class.respond_to?(:merge)
316
311
  storage_class
317
312
  end
318
313
 
319
- def parse_credentials creds
314
+ def parse_credentials(creds)
320
315
  creds = creds.respond_to?(:call) ? creds.call(self) : creds
321
316
  creds = find_credentials(creds).stringify_keys
322
317
  (creds[RailsEnvironment.get] || creds).symbolize_keys
@@ -359,26 +354,26 @@ module Paperclip
359
354
 
360
355
  def flush_writes #:nodoc:
361
356
  @queued_for_write.each do |style, file|
362
- retries = 0
357
+ retries = 0
363
358
  begin
364
359
  log("saving #{path(style)}")
365
360
  write_options = {
366
- :content_type => file.content_type,
367
- :acl => s3_permissions(style)
361
+ content_type: file.content_type,
362
+ acl: s3_permissions(style)
368
363
  }
369
364
 
370
365
  # add storage class for this style if defined
371
366
  storage_class = s3_storage_class(style)
372
- write_options.merge!(:storage_class => storage_class) if storage_class
367
+ write_options.merge!(storage_class: storage_class) if storage_class
373
368
 
374
- if @s3_server_side_encryption
375
- write_options[:server_side_encryption] = @s3_server_side_encryption
376
- end
369
+ write_options[:server_side_encryption] = @s3_server_side_encryption if @s3_server_side_encryption
377
370
 
378
371
  style_specific_options = styles[style]
379
372
 
380
373
  if style_specific_options
381
- merge_s3_headers( style_specific_options[:s3_headers], @s3_headers, @s3_metadata) if style_specific_options[:s3_headers]
374
+ if style_specific_options[:s3_headers]
375
+ merge_s3_headers(style_specific_options[:s3_headers], @s3_headers, @s3_metadata)
376
+ end
382
377
  @s3_metadata.merge!(style_specific_options[:s3_metadata]) if style_specific_options[:s3_metadata]
383
378
  end
384
379
 
@@ -392,7 +387,7 @@ module Paperclip
392
387
  rescue ::Aws::S3::Errors::SlowDown
393
388
  retries += 1
394
389
  if retries <= 5
395
- sleep((2 ** retries) * 0.5)
390
+ sleep((2**retries) * 0.5)
396
391
  retry
397
392
  else
398
393
  raise
@@ -408,7 +403,7 @@ module Paperclip
408
403
  end
409
404
 
410
405
  def flush_deletes #:nodoc:
411
- @queued_for_delete.each do |path|
406
+ @queued_for_delete.uniq.each do |path|
412
407
  begin
413
408
  log("deleting #{path}")
414
409
  s3_bucket.object(path.sub(%r{\A/}, "")).delete
@@ -421,11 +416,7 @@ module Paperclip
421
416
 
422
417
  def copy_to_local_file(style, local_dest_path)
423
418
  log("copying #{path(style)} to local file #{local_dest_path}")
424
- ::File.open(local_dest_path, 'wb') do |local_file|
425
- s3_object(style).get do |chunk|
426
- local_file.write(chunk)
427
- end
428
- end
419
+ s3_object(style).download_file(local_dest_path)
429
420
  rescue Aws::Errors::ServiceError => e
430
421
  warn("#{e} - cannot copy #{path(style)} to local file #{local_dest_path}")
431
422
  false
@@ -433,12 +424,12 @@ module Paperclip
433
424
 
434
425
  private
435
426
 
436
- def find_credentials creds
427
+ def find_credentials(creds)
437
428
  case creds
438
429
  when File
439
- YAML::load(ERB.new(File.read(creds.path)).result)
430
+ YAML::safe_load(ERB.new(File.read(creds.path)).result, [], [], true)
440
431
  when String, Pathname
441
- YAML::load(ERB.new(File.read(creds)).result)
432
+ YAML::safe_load(ERB.new(File.read(creds)).result, [], [], true)
442
433
  when Hash
443
434
  creds
444
435
  when NilClass
@@ -454,13 +445,14 @@ module Paperclip
454
445
 
455
446
  def merge_s3_headers(http_headers, s3_headers, s3_metadata)
456
447
  return if http_headers.nil?
448
+
457
449
  http_headers = http_headers.call(instance) if http_headers.respond_to?(:call)
458
- http_headers.inject({}) do |headers,(name,value)|
450
+ http_headers.inject({}) do |_headers, (name, value)|
459
451
  case name.to_s
460
452
  when /\Ax-amz-meta-(.*)/i
461
453
  s3_metadata[$1.downcase] = value
462
454
  else
463
- s3_headers[name.to_s.downcase.sub(/\Ax-amz-/,'').tr("-","_").to_sym] = value
455
+ s3_headers[name.to_s.downcase.sub(/\Ax-amz-/, "").tr("-", "_").to_sym] = value
464
456
  end
465
457
  end
466
458
  end
@@ -1,17 +1,15 @@
1
- # encoding: utf-8
2
1
  module Paperclip
3
2
  # The Style class holds the definition of a thumbnail style, applying
4
3
  # whatever processing is required to normalize the definition and delaying
5
4
  # the evaluation of block parameters until useful context is available.
6
5
 
7
6
  class Style
8
-
9
7
  attr_reader :name, :attachment, :format
10
8
 
11
9
  # Creates a Style object. +name+ is the name of the attachment,
12
10
  # +definition+ is the style definition from has_attached_file, which
13
11
  # can be string, array or hash
14
- def initialize name, definition, attachment
12
+ def initialize(name, definition, attachment)
15
13
  @name = name
16
14
  @attachment = attachment
17
15
  if definition.is_a? Hash
@@ -71,8 +69,8 @@ module Paperclip
71
69
  # Arguments other than the standard geometry, format etc are just passed through from
72
70
  # initialization and any procs are called here, just before post-processing.
73
71
  def processor_options
74
- args = {:style => name}
75
- @other_args.each do |k,v|
72
+ args = { style: name }
73
+ @other_args.each do |k, v|
76
74
  args[k] = v.respond_to?(:call) ? v.call(attachment) : v
77
75
  end
78
76
  [:processors, :geometry, :format, :whiny, :convert_options, :source_file_options].each do |k|
@@ -104,6 +102,5 @@ module Paperclip
104
102
  base = attachment.options[:default_format]
105
103
  base.respond_to?(:call) ? base.call(attachment, name) : base
106
104
  end
107
-
108
105
  end
109
106
  end
@@ -12,7 +12,8 @@ module Paperclip
12
12
  if RUBY_PLATFORM =~ /java/
13
13
  case prefix_suffix
14
14
  when String
15
- prefix, suffix = prefix_suffix, ''
15
+ prefix = prefix_suffix
16
+ suffix = ""
16
17
  when Array
17
18
  prefix, suffix = *prefix_suffix
18
19
  else
@@ -32,12 +33,10 @@ module Paperclip
32
33
  # for binary mode is ASCII-8BIT. This behavior is what's in CRuby, but not
33
34
  # in JRuby
34
35
  def binmode
35
- set_encoding('ASCII-8BIT')
36
+ set_encoding("ASCII-8BIT")
36
37
  super
37
38
  end
38
39
  end
39
40
  end
40
41
 
41
- if RUBY_PLATFORM =~ /java/
42
- ::Tempfile.send :include, Paperclip::TempfileEncoding
43
- end
42
+ ::Tempfile.include Paperclip::TempfileEncoding if RUBY_PLATFORM =~ /java/
@@ -1,6 +1,5 @@
1
1
  module Paperclip
2
2
  class TempfileFactory
3
-
4
3
  def generate(name = random_name)
5
4
  @name = name
6
5
  file = Tempfile.new([basename, extension])
@@ -1,13 +1,12 @@
1
1
  module Paperclip
2
2
  # Handles thumbnailing images that are uploaded.
3
3
  class Thumbnail < Processor
4
-
5
4
  attr_accessor :current_geometry, :target_geometry, :format, :whiny, :convert_options,
6
5
  :source_file_options, :animated, :auto_orient, :frame_index
7
6
 
8
7
  # List of formats that we need to preserve animation
9
- ANIMATED_FORMATS = %w(gif)
10
- MULTI_FRAME_FORMATS = %w(.mkv .avi .mp4 .mov .mpg .mpeg .gif)
8
+ ANIMATED_FORMATS = %w(gif).freeze
9
+ MULTI_FRAME_FORMATS = %w(.mkv .avi .mp4 .mov .mpg .mpeg .gif).freeze
11
10
 
12
11
  # Creates a Thumbnail object set to work on the +file+ given. It
13
12
  # will attempt to transform the image into one defined by +target_geometry+
@@ -31,7 +30,7 @@ module Paperclip
31
30
  super
32
31
 
33
32
  geometry = options[:geometry].to_s
34
- @crop = geometry[-1,1] == '#'
33
+ @crop = geometry[-1, 1] == "#"
35
34
  @target_geometry = options.fetch(:string_geometry_parser, Geometry).parse(geometry)
36
35
  @current_geometry = options.fetch(:file_geometry_parser, Geometry).from_file(@file)
37
36
  @source_file_options = options[:source_file_options]
@@ -40,9 +39,7 @@ module Paperclip
40
39
  @format = options[:format]
41
40
  @animated = options.fetch(:animated, true)
42
41
  @auto_orient = options.fetch(:auto_orient, true)
43
- if @auto_orient && @current_geometry.respond_to?(:auto_orient)
44
- @current_geometry.auto_orient
45
- end
42
+ @current_geometry.auto_orient if @auto_orient && @current_geometry.respond_to?(:auto_orient)
46
43
  @source_file_options = @source_file_options.split(/\s+/) if @source_file_options.respond_to?(:split)
47
44
  @convert_options = @convert_options.split(/\s+/) if @convert_options.respond_to?(:split)
48
45
 
@@ -82,10 +79,13 @@ module Paperclip
82
79
  convert(
83
80
  parameters,
84
81
  source: "#{File.expand_path(src.path)}#{frame}",
85
- dest: File.expand_path(dst.path),
82
+ dest: File.expand_path(dst.path)
86
83
  )
87
84
  rescue Terrapin::ExitStatusError => e
88
- raise Paperclip::Error, "There was an error processing the thumbnail for #{@basename}" if @whiny
85
+ if @whiny
86
+ message = "There was an error processing the thumbnail for #{@basename}:\n" + e.message
87
+ raise Paperclip::Error, message
88
+ end
89
89
  rescue Terrapin::CommandNotFoundError => e
90
90
  raise Paperclip::Errors::CommandNotFoundError.new("Could not run the `convert` command. Please install ImageMagick.")
91
91
  end
@@ -113,13 +113,13 @@ module Paperclip
113
113
  end
114
114
 
115
115
  def animated?
116
- @animated && (ANIMATED_FORMATS.include?(@format.to_s) || @format.blank?) && identified_as_animated?
116
+ @animated && (ANIMATED_FORMATS.include?(@format.to_s) || @format.blank?) && identified_as_animated?
117
117
  end
118
118
 
119
119
  # Return true if ImageMagick's +identify+ returns an animated format
120
120
  def identified_as_animated?
121
121
  if @identified_as_animated.nil?
122
- @identified_as_animated = ANIMATED_FORMATS.include? identify("-format %m :file", :file => "#{@file.path}[0]").to_s.downcase.strip
122
+ @identified_as_animated = ANIMATED_FORMATS.include? identify("-format %m :file", file: "#{@file.path}[0]").to_s.downcase.strip
123
123
  end
124
124
  @identified_as_animated
125
125
  rescue Terrapin::ExitStatusError => e
@@ -1,5 +1,5 @@
1
- require 'uri'
2
- require 'active_support/core_ext/module/delegation'
1
+ require "uri"
2
+ require "active_support/core_ext/module/delegation"
3
3
 
4
4
  module Paperclip
5
5
  class UrlGenerator
@@ -49,8 +49,8 @@ module Paperclip
49
49
 
50
50
  def timestamp_as_needed(url, options)
51
51
  if options[:timestamp] && timestamp_possible?
52
- delimiter_char = url.match(/\?.+=/) ? '&' : '?'
53
- "#{url}#{delimiter_char}#{@attachment.updated_at.to_s}"
52
+ delimiter_char = url.match(/\?.+=/) ? "&" : "?"
53
+ "#{url}#{delimiter_char}#{@attachment.updated_at}"
54
54
  else
55
55
  url
56
56
  end
@@ -72,7 +72,7 @@ module Paperclip
72
72
  if url.respond_to?(:escape)
73
73
  url.escape
74
74
  else
75
- self.class.escape(url).gsub(escape_regex){|m| "%#{m.ord.to_s(16).upcase}" }
75
+ self.class.escape(url).gsub(escape_regex) { |m| "%#{m.ord.to_s(16).upcase}" }
76
76
  end
77
77
  end
78
78
 
@@ -2,7 +2,10 @@ module Paperclip
2
2
  module Validators
3
3
  class AttachmentContentTypeValidator < ActiveModel::EachValidator
4
4
  def initialize(options)
5
- options[:allow_nil] = true unless options.has_key?(:allow_nil)
5
+ options[:allow_nil] = true unless options.key?(:allow_nil)
6
+ unless options.key?(:add_validation_errors_to)
7
+ options[:add_validation_errors_to] = Paperclip.options[:add_validation_errors_to]
8
+ end
6
9
  super
7
10
  end
8
11
 
@@ -20,10 +23,14 @@ module Paperclip
20
23
  validate_whitelist(record, attribute, value)
21
24
  validate_blacklist(record, attribute, value)
22
25
 
23
- if record.errors.include? attribute
26
+ if record.errors.include?(attribute) &&
27
+ [:both, :base].include?(options[:add_validation_errors_to])
28
+
24
29
  record.errors[attribute].each do |error|
25
30
  record.errors.add base_attribute, error
26
31
  end
32
+
33
+ record.errors.delete(attribute) if options[:add_validation_errors_to] == :base
27
34
  end
28
35
  end
29
36
 
@@ -40,7 +47,7 @@ module Paperclip
40
47
  end
41
48
 
42
49
  def mark_invalid(record, attribute, types)
43
- record.errors.add attribute, :invalid, options.merge(:types => types.join(', '))
50
+ record.errors.add attribute, :invalid, **options.merge(types: types.join(", "))
44
51
  end
45
52
 
46
53
  def allowed_types
@@ -52,7 +59,7 @@ module Paperclip
52
59
  end
53
60
 
54
61
  def check_validity!
55
- unless options.has_key?(:content_type) || options.has_key?(:not)
62
+ unless options.key?(:content_type) || options.key?(:not)
56
63
  raise ArgumentError, "You must pass in either :content_type or :not to the validator"
57
64
  end
58
65
  end
@@ -2,7 +2,10 @@ module Paperclip
2
2
  module Validators
3
3
  class AttachmentFileNameValidator < ActiveModel::EachValidator
4
4
  def initialize(options)
5
- options[:allow_nil] = true unless options.has_key?(:allow_nil)
5
+ options[:allow_nil] = true unless options.key?(:allow_nil)
6
+ unless options.key?(:add_validation_errors_to)
7
+ options[:add_validation_errors_to] = Paperclip.options[:add_validation_errors_to]
8
+ end
6
9
  super
7
10
  end
8
11
 
@@ -20,27 +23,27 @@ module Paperclip
20
23
  validate_whitelist(record, attribute, value)
21
24
  validate_blacklist(record, attribute, value)
22
25
 
23
- if record.errors.include? attribute
26
+ if record.errors.include?(attribute) &&
27
+ [:both, :base].include?(options[:add_validation_errors_to])
28
+
24
29
  record.errors[attribute].each do |error|
25
- record.errors.add base_attribute, error
30
+ record.errors.add(base_attribute, error)
26
31
  end
32
+
33
+ record.errors.delete(attribute) if options[:add_validation_errors_to] == :base
27
34
  end
28
35
  end
29
36
 
30
37
  def validate_whitelist(record, attribute, value)
31
- if allowed.present? && allowed.none? { |type| type === value }
32
- mark_invalid record, attribute, allowed
33
- end
38
+ mark_invalid record, attribute, allowed if allowed.present? && allowed.none? { |type| type === value }
34
39
  end
35
40
 
36
41
  def validate_blacklist(record, attribute, value)
37
- if forbidden.present? && forbidden.any? { |type| type === value }
38
- mark_invalid record, attribute, forbidden
39
- end
42
+ mark_invalid record, attribute, forbidden if forbidden.present? && forbidden.any? { |type| type === value }
40
43
  end
41
44
 
42
45
  def mark_invalid(record, attribute, patterns)
43
- record.errors.add attribute, :invalid, options.merge(:names => patterns.join(', '))
46
+ record.errors.add attribute, :invalid, **options.merge(names: patterns.join(", "))
44
47
  end
45
48
 
46
49
  def allowed
@@ -52,7 +55,7 @@ module Paperclip
52
55
  end
53
56
 
54
57
  def check_validity!
55
- unless options.has_key?(:matches) || options.has_key?(:not)
58
+ unless options.key?(:matches) || options.key?(:not)
56
59
  raise ArgumentError, "You must pass in either :matches or :not to the validator"
57
60
  end
58
61
  end
@@ -77,4 +80,3 @@ module Paperclip
77
80
  end
78
81
  end
79
82
  end
80
-
@@ -1,4 +1,4 @@
1
- require 'active_model/validations/presence'
1
+ require "active_model/validations/presence"
2
2
 
3
3
  module Paperclip
4
4
  module Validators
@@ -26,4 +26,3 @@ module Paperclip
26
26
  end
27
27
  end
28
28
  end
29
-
@@ -1,12 +1,10 @@
1
- require 'active_model/validations/presence'
1
+ require "active_model/validations/presence"
2
2
 
3
3
  module Paperclip
4
4
  module Validators
5
5
  class AttachmentPresenceValidator < ActiveModel::EachValidator
6
- def validate_each(record, attribute, value)
7
- if record.send("#{attribute}_file_name").blank?
8
- record.errors.add(attribute, :blank, options)
9
- end
6
+ def validate_each(record, attribute, _value)
7
+ record.errors.add(attribute, :blank, **options) if record.send("#{attribute}_file_name").blank?
10
8
  end
11
9
 
12
10
  def self.helper_method_name