paperclip 4.3.7 → 5.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of paperclip might be problematic. Click here for more details.

Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +13 -9
  3. data/Appraisals +22 -6
  4. data/CONTRIBUTING.md +6 -1
  5. data/Gemfile +2 -8
  6. data/LICENSE +1 -1
  7. data/NEWS +28 -37
  8. data/README.md +81 -63
  9. data/UPGRADING +9 -9
  10. data/features/basic_integration.feature +1 -0
  11. data/features/step_definitions/s3_steps.rb +6 -2
  12. data/gemfiles/{4.1.gemfile → 4.2.awsv2.0.gemfile} +4 -6
  13. data/gemfiles/4.2.awsv2.1.gemfile +17 -0
  14. data/gemfiles/{4.2.gemfile → 4.2.awsv2.gemfile} +1 -0
  15. data/gemfiles/5.0.awsv2.0.gemfile +17 -0
  16. data/gemfiles/5.0.awsv2.1.gemfile +17 -0
  17. data/gemfiles/{3.2.gemfile → 5.0.awsv2.gemfile} +7 -1
  18. data/lib/paperclip.rb +0 -2
  19. data/lib/paperclip/attachment.rb +9 -8
  20. data/lib/paperclip/attachment_registry.rb +2 -1
  21. data/lib/paperclip/callbacks.rb +8 -6
  22. data/lib/paperclip/glue.rb +1 -1
  23. data/lib/paperclip/has_attached_file.rb +7 -1
  24. data/lib/paperclip/io_adapters/uri_adapter.rb +11 -30
  25. data/lib/paperclip/schema.rb +1 -2
  26. data/lib/paperclip/storage/s3.rb +59 -35
  27. data/lib/paperclip/version.rb +1 -1
  28. data/paperclip.gemspec +11 -7
  29. data/spec/paperclip/attachment_registry_spec.rb +28 -0
  30. data/spec/paperclip/attachment_spec.rb +32 -6
  31. data/spec/paperclip/has_attached_file_spec.rb +24 -8
  32. data/spec/paperclip/integration_spec.rb +4 -3
  33. data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +5 -8
  34. data/spec/paperclip/io_adapters/uri_adapter_spec.rb +6 -31
  35. data/spec/paperclip/media_type_spoof_detector_spec.rb +3 -12
  36. data/spec/paperclip/paperclip_spec.rb +0 -32
  37. data/spec/paperclip/storage/s3_live_spec.rb +8 -4
  38. data/spec/paperclip/storage/s3_spec.rb +345 -165
  39. data/spec/paperclip/validators_spec.rb +2 -3
  40. data/spec/spec_helper.rb +3 -1
  41. data/spec/support/assertions.rb +7 -0
  42. data/spec/support/model_reconstruction.rb +9 -1
  43. data/spec/support/reporting.rb +11 -0
  44. metadata +45 -40
  45. data/lib/paperclip/deprecations.rb +0 -42
  46. data/lib/paperclip/locales/de.yml +0 -18
  47. data/lib/paperclip/locales/es.yml +0 -18
  48. data/lib/paperclip/locales/ja.yml +0 -18
  49. data/lib/paperclip/locales/pt-BR.yml +0 -18
  50. data/lib/paperclip/locales/zh-CN.yml +0 -18
  51. data/lib/paperclip/locales/zh-HK.yml +0 -18
  52. data/lib/paperclip/locales/zh-TW.yml +0 -18
  53. data/spec/paperclip/deprecations_spec.rb +0 -65
  54. data/spec/support/deprecations.rb +0 -9
  55. data/spec/support/rails_helpers.rb +0 -7
data/UPGRADING CHANGED
@@ -1,14 +1,14 @@
1
1
  ##################################################
2
- # NOTE FOR UPGRADING FROM PRE-3.0 VERSION #
2
+ # NOTE FOR UPGRADING FROM 4.3.0 OR EARLIER #
3
3
  ##################################################
4
4
 
5
- Paperclip 3.0 introduces a non-backward compatible change in your attachment
6
- path. This will help to prevent attachment name clashes when you have
7
- multiple attachments with the same name. If you didn't alter your
8
- attachment's path and are using Paperclip's default, you'll have to add
9
- `:path` and `:url` to your `has_attached_file` definition. For example:
5
+ Paperclip is now compatible with aws-sdk >= 2.0.0.
10
6
 
11
- has_attached_file :avatar,
12
- :path => ":rails_root/public/system/:attachment/:id/:style/:filename",
13
- :url => "/system/:attachment/:id/:style/:filename"
7
+ If you are using S3 storage, aws-sdk >= 2.0.0 requires you to make a few small
8
+ changes:
14
9
 
10
+ * You must set the `s3_region`
11
+ * If you are explicitly setting permissions anywhere, such as in an initializer,
12
+ note that the format of the permissions changed from using an underscore to
13
+ using a hyphen. For example, `:public_read` needs to be changed to
14
+ `public-read`.
@@ -69,6 +69,7 @@ Feature: Rails integration
69
69
  bucket: paperclip
70
70
  access_key_id: access_key
71
71
  secret_access_key: secret_key
72
+ s3_region: us-west-2
72
73
  """
73
74
  And I start the rails application
74
75
  When I go to the new user page
@@ -1,11 +1,15 @@
1
1
  When /^I attach the file "([^"]*)" to "([^"]*)" on S3$/ do |file_path, field|
2
2
  definition = Paperclip::AttachmentRegistry.definitions_for(User)[field.downcase.to_sym]
3
- path = "https://paperclip.s3.amazonaws.com#{definition[:path]}"
3
+ path = if defined?(::AWS)
4
+ "https://paperclip.s3.amazonaws.com#{definition[:path]}"
5
+ else
6
+ "https://paperclip.s3-us-west-2.amazonaws.com#{definition[:path]}"
7
+ end
4
8
  path.gsub!(':filename', File.basename(file_path))
5
9
  path.gsub!(/:([^\/\.]+)/) do |match|
6
10
  "([^\/\.]+)"
7
11
  end
8
- FakeWeb.register_uri(:put, Regexp.new(path), :body => "OK")
12
+ FakeWeb.register_uri(:put, Regexp.new(path), :body => defined?(::AWS) ? "OK" : "<xml></xml>")
9
13
  step "I attach the file \"#{file_path}\" to \"#{field}\""
10
14
  end
11
15
 
@@ -3,15 +3,13 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  gem "sqlite3", "~> 1.3.8", :platforms => :ruby
6
- gem "jruby-openssl", :platforms => :jruby
7
- gem "activerecord-jdbcsqlite3-adapter", :platforms => :jruby
8
- gem "rubysl", :platforms => :rbx
9
- gem "racc", :platforms => :rbx
10
6
  gem "pry"
11
- gem "rails", "~> 4.1.0"
7
+ gem "rails", "~> 4.2.0"
8
+ gem "aws-sdk", "~> 2.0.0"
12
9
 
13
10
  group :development, :test do
14
- gem "mime-types", "~> 1.16"
11
+ gem "activerecord-import"
12
+ gem "mime-types"
15
13
  gem "builder"
16
14
  gem "rubocop", :require => false
17
15
  end
@@ -0,0 +1,17 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "sqlite3", "~> 1.3.8", :platforms => :ruby
6
+ gem "pry"
7
+ gem "rails", "~> 4.2.0"
8
+ gem "aws-sdk", "~> 2.1.0"
9
+
10
+ group :development, :test do
11
+ gem "activerecord-import"
12
+ gem "mime-types", ">= 1.16", "< 4"
13
+ gem "builder"
14
+ gem "rubocop", :require => false
15
+ end
16
+
17
+ gemspec :path => "../"
@@ -9,6 +9,7 @@ gem "rubysl", :platforms => :rbx
9
9
  gem "racc", :platforms => :rbx
10
10
  gem "pry"
11
11
  gem "rails", "~> 4.2.0"
12
+ gem "aws-sdk", "~> 2.0"
12
13
 
13
14
  group :development, :test do
14
15
  gem "mime-types", "~> 1.16"
@@ -0,0 +1,17 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "sqlite3", "~> 1.3.8", :platforms => :ruby
6
+ gem "pry"
7
+ gem "rails", "5.0.0.beta3"
8
+ gem "aws-sdk", "~> 2.0.0"
9
+
10
+ group :development, :test do
11
+ gem "activerecord-import"
12
+ gem "mime-types", ">= 1.16", "< 4"
13
+ gem "builder"
14
+ gem "rubocop", :require => false
15
+ end
16
+
17
+ gemspec :path => "../"
@@ -0,0 +1,17 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "sqlite3", "~> 1.3.8", :platforms => :ruby
6
+ gem "pry"
7
+ gem "rails", "5.0.0.beta3"
8
+ gem "aws-sdk", "~> 2.1.0"
9
+
10
+ group :development, :test do
11
+ gem "activerecord-import"
12
+ gem "mime-types"
13
+ gem "builder"
14
+ gem "rubocop", :require => false
15
+ end
16
+
17
+ gemspec :path => "../"
@@ -8,7 +8,13 @@ gem "activerecord-jdbcsqlite3-adapter", :platforms => :jruby
8
8
  gem "rubysl", :platforms => :rbx
9
9
  gem "racc", :platforms => :rbx
10
10
  gem "pry"
11
- gem "rails", "~> 3.2.0"
11
+ gem "rails", :github => "rails/rails"
12
+ gem "sprockets-rails", :github => "rails/sprockets-rails"
13
+ gem "sprockets", :github => "rails/sprockets"
14
+ gem "sass-rails", :github => "rails/sass-rails"
15
+ gem "arel", :github => "rails/arel"
16
+ gem "rack", :github => "rack/rack"
17
+ gem "aws-sdk", "~> 2.0"
12
18
 
13
19
  group :development, :test do
14
20
  gem "mime-types", "~> 1.16"
@@ -56,7 +56,6 @@ require 'paperclip/has_attached_file'
56
56
  require 'paperclip/attachment_registry'
57
57
  require 'paperclip/filename_cleaner'
58
58
  require 'paperclip/rails_environment'
59
- require "paperclip/deprecations"
60
59
 
61
60
  begin
62
61
  # Use mime/types/columnar if available, for reduced memory usage
@@ -192,7 +191,6 @@ module Paperclip
192
191
  # end
193
192
  # end
194
193
  def has_attached_file(name, options = {})
195
- Paperclip::Deprecations.check
196
194
  HasAttachedFile.define_on(self, name, options)
197
195
  end
198
196
  end
@@ -2,6 +2,7 @@
2
2
  require 'uri'
3
3
  require 'paperclip/url_generator'
4
4
  require 'active_support/deprecation'
5
+ require 'active_support/core_ext/string/inflections'
5
6
 
6
7
  module Paperclip
7
8
  # The Attachment class manages the files for a given attachment. It saves
@@ -322,7 +323,7 @@ module Paperclip
322
323
  OpenSSL::HMAC.hexdigest(OpenSSL::Digest.const_get(@options[:hash_digest]).new, @options[:hash_secret], data)
323
324
  end
324
325
 
325
- # This method really shouldn't be called that often. It's expected use is
326
+ # This method really shouldn't be called that often. Its expected use is
326
327
  # in the paperclip:refresh rake task and that's it. It will regenerate all
327
328
  # thumbnails forcefully, by reobtaining the original file and going through
328
329
  # the post-process again.
@@ -426,7 +427,7 @@ module Paperclip
426
427
  def assign_attributes
427
428
  @queued_for_write[:original] = @file
428
429
  assign_file_information
429
- assign_fingerprint(@file.fingerprint)
430
+ assign_fingerprint { @file.fingerprint }
430
431
  assign_timestamps
431
432
  end
432
433
 
@@ -436,9 +437,9 @@ module Paperclip
436
437
  instance_write(:file_size, @file.size)
437
438
  end
438
439
 
439
- def assign_fingerprint(fingerprint)
440
+ def assign_fingerprint
440
441
  if instance_respond_to?(:fingerprint)
441
- instance_write(:fingerprint, fingerprint)
442
+ instance_write(:fingerprint, yield)
442
443
  end
443
444
  end
444
445
 
@@ -464,7 +465,7 @@ module Paperclip
464
465
 
465
466
  def reset_file_if_original_reprocessed
466
467
  instance_write(:file_size, @queued_for_write[:original].size)
467
- assign_fingerprint(@queued_for_write[:original].fingerprint)
468
+ assign_fingerprint { @queued_for_write[:original].fingerprint }
468
469
  reset_updater
469
470
  end
470
471
 
@@ -500,7 +501,7 @@ module Paperclip
500
501
 
501
502
  instance.run_paperclip_callbacks(:post_process) do
502
503
  instance.run_paperclip_callbacks(:"#{name}_post_process") do
503
- unless @options[:check_validity_before_processing] && instance.errors.any?
504
+ if !@options[:check_validity_before_processing] || !instance.errors.any?
504
505
  post_process_styles(*style_args)
505
506
  end
506
507
  end
@@ -521,7 +522,7 @@ module Paperclip
521
522
 
522
523
  @queued_for_write[name] = style.processors.inject(@queued_for_write[:original]) do |file, processor|
523
524
  file = Paperclip.processor(processor).make(file, style.processor_options, self)
524
- intermediate_files << file
525
+ intermediate_files << file unless file == @queued_for_write[:original]
525
526
  file
526
527
  end
527
528
 
@@ -586,7 +587,7 @@ module Paperclip
586
587
 
587
588
  # You can either specifiy :restricted_characters or you can define your own
588
589
  # :filename_cleaner object. This object needs to respond to #call and takes
589
- # the filename that will be cleaned. It should return the cleaned filenme.
590
+ # the filename that will be cleaned. It should return the cleaned filename.
590
591
  def filename_cleaner
591
592
  @options[:filename_cleaner] || FilenameCleaner.new(@options[:restricted_characters])
592
593
  end
@@ -51,7 +51,8 @@ module Paperclip
51
51
  end
52
52
 
53
53
  def definitions_for(klass)
54
- klass.ancestors.each_with_object({}) do |ancestor, inherited_definitions|
54
+ parent_classes = klass.ancestors.reverse
55
+ parent_classes.each_with_object({}) do |ancestor, inherited_definitions|
55
56
  inherited_definitions.deep_merge! @attachments[ancestor]
56
57
  end
57
58
  end
@@ -7,7 +7,7 @@ module Paperclip
7
7
 
8
8
  module Defining
9
9
  def define_paperclip_callbacks(*callbacks)
10
- define_callbacks(*[callbacks, {:terminator => callback_terminator}].flatten)
10
+ define_callbacks(*[callbacks, { terminator: hasta_la_vista_baby }].flatten)
11
11
  callbacks.each do |callback|
12
12
  eval <<-end_callbacks
13
13
  def before_#{callback}(*args, &blk)
@@ -22,11 +22,13 @@ module Paperclip
22
22
 
23
23
  private
24
24
 
25
- def callback_terminator
26
- if ::ActiveSupport::VERSION::STRING >= '4.1'
27
- lambda { |target, result| result == false }
28
- else
29
- 'result == false'
25
+ def hasta_la_vista_baby
26
+ lambda do |_, result|
27
+ if result.respond_to?(:call)
28
+ result.call == false
29
+ else
30
+ result == false
31
+ end
30
32
  end
31
33
  end
32
34
  end
@@ -8,7 +8,7 @@ module Paperclip
8
8
  base.extend ClassMethods
9
9
  base.send :include, Callbacks
10
10
  base.send :include, Validators
11
- base.send :include, Schema if defined? ActiveRecord
11
+ base.send :include, Schema if defined? ActiveRecord::Base
12
12
 
13
13
  locale_path = Dir.glob(File.dirname(__FILE__) + "/locales/*.{rb,yml}")
14
14
  I18n.load_path += locale_path unless I18n.load_path.include?(locale_path)
@@ -91,7 +91,13 @@ module Paperclip
91
91
  name = @name
92
92
  @klass.send(:after_save) { send(name).send(:save) }
93
93
  @klass.send(:before_destroy) { send(name).send(:queue_all_for_delete) }
94
- @klass.send(:after_commit, :on => :destroy) { send(name).send(:flush_deletes) }
94
+ if @klass.respond_to?(:after_commit)
95
+ @klass.send(:after_commit, on: :destroy) do
96
+ send(name).send(:flush_deletes)
97
+ end
98
+ else
99
+ @klass.send(:after_destroy) { send(name).send(:flush_deletes) }
100
+ end
95
101
  end
96
102
 
97
103
  def add_paperclip_callbacks
@@ -2,8 +2,6 @@ require 'open-uri'
2
2
 
3
3
  module Paperclip
4
4
  class UriAdapter < AbstractAdapter
5
- attr_writer :content_type
6
-
7
5
  def initialize(target)
8
6
  @target = target
9
7
  @content = download_content
@@ -11,40 +9,23 @@ module Paperclip
11
9
  @tempfile = copy_to_tempfile(@content)
12
10
  end
13
11
 
14
- private
15
-
16
- def cache_current_values
17
- self.content_type = content_type_from_content || "text/html"
18
-
19
- self.original_filename = filename_from_content_disposition ||
20
- filename_from_path ||
21
- default_filename
22
- @size = @content.size
23
- end
12
+ attr_writer :content_type
24
13
 
25
- def content_type_from_content
26
- if @content.respond_to?(:content_type)
27
- @content.content_type
28
- end
29
- end
14
+ private
30
15
 
31
- def filename_from_content_disposition
32
- if @content.meta.has_key?("content-disposition")
33
- @content.meta["content-disposition"].
34
- match(/filename="([^"]*)"/)[1]
35
- end
16
+ def download_content
17
+ open(@target)
36
18
  end
37
19
 
38
- def filename_from_path
39
- @target.path.split("/").last
40
- end
20
+ def cache_current_values
21
+ @original_filename = @target.path.split("/").last
22
+ @original_filename ||= "index.html"
23
+ self.original_filename = @original_filename.strip
41
24
 
42
- def default_filename
43
- "index.html"
44
- end
25
+ @content_type = @content.content_type if @content.respond_to?(:content_type)
26
+ @content_type ||= "text/html"
45
27
 
46
- def download_content
47
- open(@target)
28
+ @size = @content.size
48
29
  end
49
30
 
50
31
  def copy_to_tempfile(src)
@@ -38,8 +38,7 @@ module Paperclip
38
38
  options = attachment_names.extract_options!
39
39
 
40
40
  attachment_names.each do |attachment_name|
41
- COLUMNS.each_pair do |column_name, column_type|
42
- column_options = options.merge(options[column_name.to_sym] || {})
41
+ COLUMNS.keys.each do |column_name|
43
42
  remove_column(table_name, "#{attachment_name}_#{column_name}")
44
43
  end
45
44
  end
@@ -4,7 +4,7 @@ module Paperclip
4
4
  # distribution. You can find out more about it at http://aws.amazon.com/s3
5
5
  #
6
6
  # To use Paperclip with S3, include the +aws-sdk+ gem in your Gemfile:
7
- # gem 'aws-sdk', '~> 1.6'
7
+ # gem 'aws-sdk'
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
@@ -41,7 +41,7 @@ module Paperclip
41
41
  # * +s3_permissions+: This is a String that should be one of the "canned" access
42
42
  # policies that S3 provides (more information can be found here:
43
43
  # http://docs.aws.amazon.com/AmazonS3/latest/dev/ACLOverview.html)
44
- # The default for Paperclip is :public_read.
44
+ # The default for Paperclip is public-read.
45
45
  #
46
46
  # You can set permission on a per style bases by doing the following:
47
47
  # :s3_permissions => {
@@ -61,7 +61,7 @@ module Paperclip
61
61
  # * +bucket+: This is the name of the S3 bucket that will store your files. Remember
62
62
  # that the bucket must be unique across all of Amazon S3. If the bucket does not exist
63
63
  # Paperclip will attempt to create it. The bucket name will not be interpolated.
64
- # You can define the bucket as a Proc if you want to determine it's name at runtime.
64
+ # You can define the bucket as a Proc if you want to determine its name at runtime.
65
65
  # Paperclip will call that Proc with attachment as the only argument.
66
66
  # * +s3_host_alias+: The fully-qualified domain name (FQDN) that is the alias to the
67
67
  # S3 domain of your bucket. Used with the :s3_alias_url url interpolation. See the
@@ -93,6 +93,7 @@ module Paperclip
93
93
  # S3 (strictly speaking) does not support directories, you can still use a / to
94
94
  # separate parts of your file name.
95
95
  # * +s3_host_name+: If you are using your bucket in Tokyo region etc, write host_name.
96
+ # * +s3_region+: For aws-sdk v2, s3_region is required.
96
97
  # * +s3_metadata+: These key/value pairs will be stored with the
97
98
  # object. This option works by prefixing each key with
98
99
  # "x-amz-meta-" before sending it as a header on the object
@@ -112,22 +113,33 @@ module Paperclip
112
113
 
113
114
  module S3
114
115
  def self.extended base
115
- begin
116
- require 'aws-sdk'
117
- rescue LoadError => e
118
- e.message << " (You may need to install the aws-sdk gem)"
119
- raise e
120
- end unless defined?(AWS::Core)
116
+ unless defined?(AWS_CLASS)
117
+ begin
118
+ require 'aws-sdk'
119
+ const_set('AWS_CLASS', defined?(::Aws) ? ::Aws : ::AWS)
120
+ const_set('AWS_BASE_ERROR',
121
+ defined?(::Aws) ? Aws::Errors::ServiceError : AWS::Errors::Base)
122
+ const_set('DEFAULT_PERMISSION',
123
+ defined?(::AWS) ? :public_read : :'public-read')
124
+
125
+ rescue LoadError => e
126
+ e.message << " (You may need to install the aws-sdk gem)"
127
+ raise e
128
+ end
129
+ if Gem::Version.new(AWS_CLASS::VERSION) >= Gem::Version.new(2) && Gem::Version.new(AWS_CLASS::VERSION) <= Gem::Version.new("2.0.33")
130
+ raise LoadError, "paperclip does not support aws-sdk versions 2.0.0 - 2.0.33. Please upgrade aws-sdk to a newer version."
131
+ end
132
+ end
121
133
 
122
134
  # Overriding log formatter to make sure it return a UTF-8 string
123
- if defined?(AWS::Core::LogFormatter)
124
- AWS::Core::LogFormatter.class_eval do
135
+ if defined?(AWS_CLASS::Core::LogFormatter)
136
+ AWS_CLASS::Core::LogFormatter.class_eval do
125
137
  def summarize_hash(hash)
126
138
  hash.map { |key, value| ":#{key}=>#{summarize_value(value)}".force_encoding('UTF-8') }.sort.join(',')
127
139
  end
128
140
  end
129
- elsif defined?(AWS::Core::ClientLogging)
130
- AWS::Core::ClientLogging.class_eval do
141
+ elsif defined?(AWS_CLASS::Core::ClientLogging)
142
+ AWS_CLASS::Core::ClientLogging.class_eval do
131
143
  def sanitize_hash(hash)
132
144
  hash.map { |key, value| "#{sanitize_value(key)}=>#{sanitize_value(value)}".force_encoding('UTF-8') }.sort.join(',')
133
145
  end
@@ -141,7 +153,7 @@ module Paperclip
141
153
  Proc.new do |style, attachment|
142
154
  permission = (@s3_permissions[style.to_s.to_sym] || @s3_permissions[:default])
143
155
  permission = permission.call(attachment, style) if permission.respond_to?(:call)
144
- (permission == :public_read) ? 'http'.freeze : 'https'.freeze
156
+ (permission == DEFAULT_PERMISSION) ? 'http'.freeze : 'https'.freeze
145
157
  end
146
158
  @s3_metadata = @options[:s3_metadata] || {}
147
159
  @s3_headers = {}
@@ -149,7 +161,7 @@ module Paperclip
149
161
 
150
162
  @s3_storage_class = set_storage_class(@options[:s3_storage_class])
151
163
 
152
- @s3_server_side_encryption = :aes256
164
+ @s3_server_side_encryption = "AES256"
153
165
  if @options[:s3_server_side_encryption].blank?
154
166
  @s3_server_side_encryption = false
155
167
  end
@@ -182,8 +194,11 @@ module Paperclip
182
194
 
183
195
  def expiring_url(time = 3600, style_name = default_style)
184
196
  if path(style_name)
185
- base_options = { :expires => time, :secure => use_secure_protocol?(style_name) }
186
- s3_object(style_name).url_for(:read, base_options.merge(s3_url_options)).to_s
197
+ base_options = { expires_in: time }
198
+ s3_object(style_name).presigned_url(
199
+ :get,
200
+ base_options.merge(s3_url_options),
201
+ ).to_s
187
202
  else
188
203
  url(style_name)
189
204
  end
@@ -200,6 +215,13 @@ module Paperclip
200
215
  host_name || s3_credentials[:s3_host_name] || "s3.amazonaws.com".freeze
201
216
  end
202
217
 
218
+ def s3_region
219
+ region = @options[:s3_region]
220
+ region = region.call(self) if region.is_a?(Proc)
221
+
222
+ region || s3_credentials[:s3_region]
223
+ end
224
+
203
225
  def s3_host_alias
204
226
  @s3_host_alias = @options[:s3_host_alias]
205
227
  @s3_host_alias = @s3_host_alias.call(self) if @s3_host_alias.respond_to?(:call)
@@ -220,7 +242,7 @@ module Paperclip
220
242
 
221
243
  def s3_interface
222
244
  @s3_interface ||= begin
223
- config = { :s3_endpoint => s3_host_name }
245
+ config = { region: s3_region }
224
246
 
225
247
  if using_http_proxy?
226
248
 
@@ -234,7 +256,7 @@ module Paperclip
234
256
  config[:proxy_uri] = URI::HTTP.build(proxy_opts)
235
257
  end
236
258
 
237
- [:access_key_id, :secret_access_key, :credential_provider].each do |opt|
259
+ [:access_key_id, :secret_access_key, :credential_provider, :credentials].each do |opt|
238
260
  config[opt] = s3_credentials[opt] if s3_credentials[opt]
239
261
  end
240
262
 
@@ -244,15 +266,19 @@ module Paperclip
244
266
 
245
267
  def obtain_s3_instance_for(options)
246
268
  instances = (Thread.current[:paperclip_s3_instances] ||= {})
247
- instances[options] ||= AWS::S3.new(options)
269
+ instances[options] ||= AWS_CLASS::S3::Resource.new(options)
248
270
  end
249
271
 
250
272
  def s3_bucket
251
- @s3_bucket ||= s3_interface.buckets[bucket_name]
273
+ @s3_bucket ||= s3_interface.bucket(bucket_name)
274
+ end
275
+
276
+ def style_name_as_path(style_name)
277
+ path(style_name).sub(%r{\A/},'')
252
278
  end
253
279
 
254
280
  def s3_object style_name = default_style
255
- s3_bucket.objects[path(style_name).sub(%r{\A/},'')]
281
+ s3_bucket.object style_name_as_path(style_name)
256
282
  end
257
283
 
258
284
  def using_http_proxy?
@@ -277,7 +303,7 @@ module Paperclip
277
303
 
278
304
  def set_permissions permissions
279
305
  permissions = { :default => permissions } unless permissions.respond_to?(:merge)
280
- permissions.merge :default => (permissions[:default] || :public_read)
306
+ permissions.merge :default => (permissions[:default] || DEFAULT_PERMISSION)
281
307
  end
282
308
 
283
309
  def set_storage_class(storage_class)
@@ -297,7 +323,7 @@ module Paperclip
297
323
  else
298
324
  false
299
325
  end
300
- rescue AWS::Errors::Base => e
326
+ rescue AWS_BASE_ERROR => e
301
327
  false
302
328
  end
303
329
 
@@ -323,7 +349,7 @@ module Paperclip
323
349
  end
324
350
 
325
351
  def create_bucket
326
- s3_interface.buckets.create(bucket_name)
352
+ s3_interface.bucket(bucket_name).create
327
353
  end
328
354
 
329
355
  def flush_writes #:nodoc:
@@ -331,11 +357,9 @@ module Paperclip
331
357
  retries = 0
332
358
  begin
333
359
  log("saving #{path(style)}")
334
- acl = @s3_permissions[style] || @s3_permissions[:default]
335
- acl = acl.call(self, style) if acl.respond_to?(:call)
336
360
  write_options = {
337
361
  :content_type => file.content_type,
338
- :acl => acl
362
+ :acl => s3_permissions(style)
339
363
  }
340
364
 
341
365
  # add storage class for this style if defined
@@ -356,11 +380,11 @@ module Paperclip
356
380
  write_options[:metadata] = @s3_metadata unless @s3_metadata.empty?
357
381
  write_options.merge!(@s3_headers)
358
382
 
359
- s3_object(style).write(file, write_options)
360
- rescue AWS::S3::Errors::NoSuchBucket
383
+ s3_object(style).upload_file(file.path, write_options)
384
+ rescue AWS_CLASS::S3::Errors::NoSuchBucket
361
385
  create_bucket
362
386
  retry
363
- rescue AWS::S3::Errors::SlowDown
387
+ rescue AWS_CLASS::S3::Errors::SlowDown
364
388
  retries += 1
365
389
  if retries <= 5
366
390
  sleep((2 ** retries) * 0.5)
@@ -382,8 +406,8 @@ module Paperclip
382
406
  @queued_for_delete.each do |path|
383
407
  begin
384
408
  log("deleting #{path}")
385
- s3_bucket.objects[path.sub(%r{\A/},'')].delete
386
- rescue AWS::Errors::Base => e
409
+ s3_bucket.object(path.sub(%r{\A/}, "")).delete
410
+ rescue AWS_BASE_ERROR => e
387
411
  # Ignore this.
388
412
  end
389
413
  end
@@ -393,11 +417,11 @@ module Paperclip
393
417
  def copy_to_local_file(style, local_dest_path)
394
418
  log("copying #{path(style)} to local file #{local_dest_path}")
395
419
  ::File.open(local_dest_path, 'wb') do |local_file|
396
- s3_object(style).read do |chunk|
420
+ s3_object(style).get do |chunk|
397
421
  local_file.write(chunk)
398
422
  end
399
423
  end
400
- rescue AWS::Errors::Base => e
424
+ rescue AWS_BASE_ERROR => e
401
425
  warn("#{e} - cannot copy #{path(style)} to local file #{local_dest_path}")
402
426
  false
403
427
  end