paperclip 2.4.5 → 2.5.0
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.
- data/.gitignore +22 -0
- data/.travis.yml +13 -0
- data/Appraisals +14 -0
- data/CONTRIBUTING.md +38 -0
- data/Gemfile +5 -0
- data/NEWS +23 -0
- data/README.md +72 -42
- data/Rakefile +1 -46
- data/cucumber/paperclip_steps.rb +6 -0
- data/features/basic_integration.feature +46 -0
- data/features/rake_tasks.feature +63 -0
- data/features/step_definitions/attachment_steps.rb +65 -0
- data/features/step_definitions/html_steps.rb +15 -0
- data/features/step_definitions/rails_steps.rb +182 -0
- data/features/step_definitions/s3_steps.rb +14 -0
- data/features/step_definitions/web_steps.rb +209 -0
- data/features/support/env.rb +8 -0
- data/features/support/fakeweb.rb +3 -0
- data/features/support/fixtures/.boot_config.rb.swo +0 -0
- data/features/support/fixtures/boot_config.txt +15 -0
- data/features/support/fixtures/gemfile.txt +5 -0
- data/features/support/fixtures/preinitializer.txt +20 -0
- data/features/support/paths.rb +28 -0
- data/features/support/rails.rb +46 -0
- data/features/support/selectors.rb +19 -0
- data/gemfiles/rails2.gemfile +9 -0
- data/gemfiles/rails3.gemfile +9 -0
- data/gemfiles/rails3_1.gemfile +9 -0
- data/lib/paperclip.rb +26 -19
- data/lib/paperclip/attachment.rb +123 -109
- data/lib/paperclip/interpolations.rb +7 -4
- data/lib/paperclip/matchers.rb +33 -2
- data/lib/paperclip/missing_attachment_styles.rb +1 -1
- data/lib/paperclip/railtie.rb +5 -0
- data/lib/paperclip/schema.rb +39 -0
- data/lib/paperclip/storage/fog.rb +21 -10
- data/lib/paperclip/storage/s3.rb +107 -40
- data/lib/paperclip/style.rb +13 -5
- data/lib/paperclip/url_generator.rb +64 -0
- data/lib/paperclip/version.rb +1 -1
- data/lib/tasks/paperclip.rake +1 -1
- data/paperclip.gemspec +41 -0
- data/test/.gitignore +1 -0
- data/test/attachment_test.rb +155 -168
- data/test/fixtures/question?mark.png +0 -0
- data/test/helper.rb +24 -1
- data/test/interpolations_test.rb +16 -2
- data/test/paperclip_missing_attachment_styles_test.rb +16 -0
- data/test/paperclip_test.rb +72 -22
- data/test/schema_test.rb +98 -0
- data/test/storage/filesystem_test.rb +2 -2
- data/test/{fog_test.rb → storage/fog_test.rb} +35 -8
- data/test/storage/s3_live_test.rb +63 -13
- data/test/storage/s3_test.rb +394 -91
- data/test/style_test.rb +50 -21
- data/test/support/mock_attachment.rb +22 -0
- data/test/support/mock_interpolator.rb +24 -0
- data/test/support/mock_model.rb +2 -0
- data/test/support/mock_url_generator_builder.rb +27 -0
- data/test/url_generator_test.rb +187 -0
- metadata +307 -125
- data/lib/paperclip/options.rb +0 -78
- data/test/options_test.rb +0 -75
@@ -137,11 +137,11 @@ module Paperclip
|
|
137
137
|
attachment.fingerprint
|
138
138
|
end
|
139
139
|
|
140
|
-
# Returns a the attachment hash. See Paperclip::Attachment#
|
140
|
+
# Returns a the attachment hash. See Paperclip::Attachment#hash_key for
|
141
141
|
# more details.
|
142
142
|
def hash attachment=nil, style_name=nil
|
143
143
|
if attachment && style_name
|
144
|
-
attachment.
|
144
|
+
attachment.hash_key(style_name)
|
145
145
|
else
|
146
146
|
super()
|
147
147
|
end
|
@@ -150,10 +150,13 @@ module Paperclip
|
|
150
150
|
# Returns the id of the instance in a split path form. e.g. returns
|
151
151
|
# 000/001/234 for an id of 1234.
|
152
152
|
def id_partition attachment, style_name
|
153
|
-
|
153
|
+
case id = attachment.instance.id
|
154
|
+
when Integer
|
154
155
|
("%09d" % id).scan(/\d{3}/).join("/")
|
155
|
-
|
156
|
+
when String
|
156
157
|
id.scan(/.{3}/).first(3).join("/")
|
158
|
+
else
|
159
|
+
nil
|
157
160
|
end
|
158
161
|
end
|
159
162
|
|
data/lib/paperclip/matchers.rb
CHANGED
@@ -5,13 +5,15 @@ require 'paperclip/matchers/validate_attachment_size_matcher'
|
|
5
5
|
|
6
6
|
module Paperclip
|
7
7
|
module Shoulda
|
8
|
-
# Provides
|
8
|
+
# Provides RSpec-compatible & Test::Unit-compatible matchers for testing Paperclip attachments.
|
9
|
+
#
|
10
|
+
# *RSpec*
|
9
11
|
#
|
10
12
|
# In spec_helper.rb, you'll need to require the matchers:
|
11
13
|
#
|
12
14
|
# require "paperclip/matchers"
|
13
15
|
#
|
14
|
-
# And
|
16
|
+
# And _include_ the module:
|
15
17
|
#
|
16
18
|
# Spec::Runner.configure do |config|
|
17
19
|
# config.include Paperclip::Shoulda::Matchers
|
@@ -27,6 +29,35 @@ module Paperclip
|
|
27
29
|
# it { should validate_attachment_size(:avatar).
|
28
30
|
# less_than(2.megabytes) }
|
29
31
|
# end
|
32
|
+
#
|
33
|
+
#
|
34
|
+
# *TestUnit*
|
35
|
+
#
|
36
|
+
# In test_helper.rb, you'll need to require the matchers as well:
|
37
|
+
#
|
38
|
+
# require "paperclip/matchers"
|
39
|
+
#
|
40
|
+
# And _extend_ the module:
|
41
|
+
#
|
42
|
+
# class ActiveSupport::TestCase
|
43
|
+
# extend Paperclip::Shoulda::Matchers
|
44
|
+
#
|
45
|
+
# #...other initializers...#
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# Example:
|
49
|
+
# require 'test_helper'
|
50
|
+
#
|
51
|
+
# class UserTest < ActiveSupport::TestCase
|
52
|
+
# should have_attached_file(:avatar)
|
53
|
+
# should validate_attachment_presence(:avatar)
|
54
|
+
# should validate_attachment_content_type(:avatar).
|
55
|
+
# allowing('image/png', 'image/gif').
|
56
|
+
# rejecting('text/plain', 'text/xml')
|
57
|
+
# should validate_attachment_size(:avatar).
|
58
|
+
# less_than(2.megabytes)
|
59
|
+
# end
|
60
|
+
#
|
30
61
|
module Matchers
|
31
62
|
end
|
32
63
|
end
|
@@ -70,7 +70,7 @@ module Paperclip
|
|
70
70
|
Hash.new.tap do |missing_styles|
|
71
71
|
current_styles.each do |klass, attachment_definitions|
|
72
72
|
attachment_definitions.each do |attachment_name, styles|
|
73
|
-
registered = registered_styles[klass][attachment_name] rescue []
|
73
|
+
registered = registered_styles[klass][attachment_name] || [] rescue []
|
74
74
|
missed = styles - registered
|
75
75
|
if missed.present?
|
76
76
|
klass_sym = klass.to_s.to_sym
|
data/lib/paperclip/railtie.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'paperclip'
|
2
|
+
require 'paperclip/schema'
|
2
3
|
|
3
4
|
module Paperclip
|
4
5
|
if defined? Rails::Railtie
|
@@ -21,6 +22,10 @@ module Paperclip
|
|
21
22
|
File.send(:include, Paperclip::Upfile)
|
22
23
|
|
23
24
|
Paperclip.options[:logger] = defined?(ActiveRecord) ? ActiveRecord::Base.logger : Rails.logger
|
25
|
+
|
26
|
+
ActiveRecord::ConnectionAdapters::AbstractAdapter.send(:include, Paperclip::Schema)
|
27
|
+
ActiveRecord::ConnectionAdapters::Table.send(:include, Paperclip::Schema)
|
28
|
+
ActiveRecord::ConnectionAdapters::TableDefinition.send(:include, Paperclip::Schema)
|
24
29
|
end
|
25
30
|
end
|
26
31
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Paperclip
|
2
|
+
# Provides two helpers that can be used in migrations.
|
3
|
+
#
|
4
|
+
# In order to use this module, the target class should implement a
|
5
|
+
# +column+ method that takes the column name and type, both as symbols,
|
6
|
+
# as well as a +remove_column+ method that takes a table and column name,
|
7
|
+
# also both symbols.
|
8
|
+
module Schema
|
9
|
+
@@columns = {:file_name => :string,
|
10
|
+
:content_type => :string,
|
11
|
+
:file_size => :integer,
|
12
|
+
:updated_at => :datetime}
|
13
|
+
|
14
|
+
def has_attached_file(attachment_name)
|
15
|
+
with_columns_for(attachment_name) do |column_name, column_type|
|
16
|
+
column(column_name, column_type)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def drop_attached_file(table_name, attachment_name)
|
21
|
+
with_columns_for(attachment_name) do |column_name, column_type|
|
22
|
+
remove_column(table_name, column_name)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
def with_columns_for(attachment_name)
|
29
|
+
@@columns.each do |suffix, column_type|
|
30
|
+
column_name = full_column_name(attachment_name, suffix)
|
31
|
+
yield column_name, column_type
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def full_column_name(attachment_name, column_name)
|
36
|
+
"#{attachment_name}_#{column_name}".to_sym
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -41,9 +41,9 @@ module Paperclip
|
|
41
41
|
end unless defined?(Fog)
|
42
42
|
|
43
43
|
base.instance_eval do
|
44
|
-
unless @options
|
45
|
-
@options
|
46
|
-
@options
|
44
|
+
unless @options[:url].to_s.match(/^:fog.*url$/)
|
45
|
+
@options[:path] = @options[:path].gsub(/:url/, @options[:url])
|
46
|
+
@options[:url] = ':fog_public_url'
|
47
47
|
end
|
48
48
|
Paperclip.interpolates(:fog_public_url) do |attachment, style|
|
49
49
|
attachment.public_url(style)
|
@@ -51,6 +51,8 @@ module Paperclip
|
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
|
+
AWS_BUCKET_SUBDOMAIN_RESTRICTON_REGEX = /^(?:[a-z]|\d(?!\d{0,2}(?:\.\d{1,3}){3}$))(?:[a-z0-9]|\.(?![\.\-])|\-(?![\.])){1,61}[a-z0-9]$/
|
55
|
+
|
54
56
|
def exists?(style = default_style)
|
55
57
|
if original_filename
|
56
58
|
!!directory.files.head(path(style))
|
@@ -60,16 +62,16 @@ module Paperclip
|
|
60
62
|
end
|
61
63
|
|
62
64
|
def fog_credentials
|
63
|
-
@fog_credentials ||= parse_credentials(@options
|
65
|
+
@fog_credentials ||= parse_credentials(@options[:fog_credentials])
|
64
66
|
end
|
65
67
|
|
66
68
|
def fog_file
|
67
|
-
@fog_file ||= @options
|
69
|
+
@fog_file ||= @options[:fog_file] || {}
|
68
70
|
end
|
69
71
|
|
70
72
|
def fog_public
|
71
73
|
return @fog_public if defined?(@fog_public)
|
72
|
-
@fog_public = defined?(@options
|
74
|
+
@fog_public = defined?(@options[:fog_public]) ? @options[:fog_public] : true
|
73
75
|
end
|
74
76
|
|
75
77
|
def flush_writes
|
@@ -122,11 +124,20 @@ module Paperclip
|
|
122
124
|
end
|
123
125
|
|
124
126
|
def public_url(style = default_style)
|
125
|
-
if @options
|
126
|
-
host = (@options
|
127
|
+
if @options[:fog_host]
|
128
|
+
host = (@options[:fog_host] =~ /%d/) ? @options[:fog_host] % (path(style).hash % 4) : @options[:fog_host]
|
127
129
|
"#{host}/#{path(style)}"
|
128
130
|
else
|
129
|
-
|
131
|
+
if fog_credentials[:provider] == 'AWS'
|
132
|
+
if @options[:fog_directory].to_s =~ Fog::AWS_BUCKET_SUBDOMAIN_RESTRICTON_REGEX
|
133
|
+
"https://#{@options[:fog_directory]}.s3.amazonaws.com/#{path(style)}"
|
134
|
+
else
|
135
|
+
# directory is not a valid subdomain, so use path style for access
|
136
|
+
"https://s3.amazonaws.com/#{@options[:fog_directory]}/#{path(style)}"
|
137
|
+
end
|
138
|
+
else
|
139
|
+
directory.files.new(:key => path(style)).public_url
|
140
|
+
end
|
130
141
|
end
|
131
142
|
end
|
132
143
|
|
@@ -156,7 +167,7 @@ module Paperclip
|
|
156
167
|
end
|
157
168
|
|
158
169
|
def directory
|
159
|
-
@directory ||= connection.directories.new(:key => @options
|
170
|
+
@directory ||= connection.directories.new(:key => @options[:fog_directory])
|
160
171
|
end
|
161
172
|
end
|
162
173
|
end
|
data/lib/paperclip/storage/s3.rb
CHANGED
@@ -2,6 +2,9 @@ module Paperclip
|
|
2
2
|
module Storage
|
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
|
+
#
|
6
|
+
# To use Paperclip with S3, include the +aws-sdk+ gem in your Gemfile:
|
7
|
+
# gem 'aws-sdk'
|
5
8
|
# There are a few S3-specific options for has_attached_file:
|
6
9
|
# * +s3_credentials+: Takes a path, a File, or a Hash. The path (or File) must point
|
7
10
|
# to a YAML file containing the +access_key_id+ and +secret_access_key+ that Amazon
|
@@ -38,7 +41,9 @@ module Paperclip
|
|
38
41
|
# * +s3_protocol+: The protocol for the URLs generated to your S3 assets. Can be either
|
39
42
|
# 'http' or 'https'. Defaults to 'http' when your :s3_permissions are :public_read (the
|
40
43
|
# default), and 'https' when your :s3_permissions are anything else.
|
41
|
-
# * +s3_headers+: A hash of headers
|
44
|
+
# * +s3_headers+: A hash of headers or a Proc. You may specify a hash such as
|
45
|
+
# {'Expires' => 1.year.from_now.httpdate}. If you use a Proc, headers are determined at
|
46
|
+
# runtime. Paperclip will call that Proc with attachment as the only argument.
|
42
47
|
# * +bucket+: This is the name of the S3 bucket that will store your files. Remember
|
43
48
|
# that the bucket must be unique across all of Amazon S3. If the bucket does not exist
|
44
49
|
# Paperclip will attempt to create it. The bucket name will not be interpolated.
|
@@ -67,41 +72,56 @@ module Paperclip
|
|
67
72
|
# S3 (strictly speaking) does not support directories, you can still use a / to
|
68
73
|
# separate parts of your file name.
|
69
74
|
# * +s3_host_name+: If you are using your bucket in Tokyo region etc, write host_name.
|
75
|
+
# * +s3_metadata+: These key/value pairs will be stored with the
|
76
|
+
# object. This option works by prefixing each key with
|
77
|
+
# "x-amz-meta-" before sending it as a header on the object
|
78
|
+
# upload request.
|
79
|
+
# * +s3_storage_class+: If this option is set to
|
80
|
+
# <tt>:reduced_redundancy</tt>, the object will be stored using Reduced
|
81
|
+
# Redundancy Storage. RRS enables customers to reduce their
|
82
|
+
# costs by storing non-critical, reproducible data at lower
|
83
|
+
# levels of redundancy than Amazon S3's standard storage.
|
70
84
|
module S3
|
71
85
|
def self.extended base
|
72
86
|
begin
|
73
|
-
require 'aws
|
87
|
+
require 'aws-sdk'
|
74
88
|
rescue LoadError => e
|
75
|
-
e.message << " (You may need to install the aws-
|
89
|
+
e.message << " (You may need to install the aws-sdk gem)"
|
76
90
|
raise e
|
77
|
-
end unless defined?(AWS::
|
91
|
+
end unless defined?(AWS::Core)
|
78
92
|
|
79
93
|
base.instance_eval do
|
80
|
-
@s3_options = @options
|
81
|
-
@s3_permissions = set_permissions(@options
|
82
|
-
@s3_protocol = @options
|
94
|
+
@s3_options = @options[:s3_options] || {}
|
95
|
+
@s3_permissions = set_permissions(@options[:s3_permissions])
|
96
|
+
@s3_protocol = @options[:s3_protocol] ||
|
83
97
|
Proc.new do |style, attachment|
|
84
98
|
permission = (@s3_permissions[style.to_sym] || @s3_permissions[:default])
|
85
99
|
permission = permission.call(attachment, style) if permission.is_a?(Proc)
|
86
100
|
(permission == :public_read) ? 'http' : 'https'
|
87
101
|
end
|
88
|
-
@
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
102
|
+
@s3_metadata = @options[:s3_metadata] || {}
|
103
|
+
@s3_headers = @options[:s3_headers] || {}
|
104
|
+
@s3_headers = @s3_headers.call(instance) if @s3_headers.is_a?(Proc)
|
105
|
+
@s3_headers = (@s3_headers).inject({}) do |headers,(name,value)|
|
106
|
+
case name.to_s
|
107
|
+
when /^x-amz-meta-(.*)/i
|
108
|
+
@s3_metadata[$1.downcase] = value
|
109
|
+
else
|
110
|
+
name = name.to_s.downcase.sub(/^x-amz-/,'').tr("-","_").to_sym
|
111
|
+
headers[name] = value
|
112
|
+
end
|
113
|
+
headers
|
93
114
|
end
|
94
|
-
@options.url = @options.url.inspect if @options.url.is_a?(Symbol)
|
95
115
|
|
96
|
-
@
|
97
|
-
|
98
|
-
|
116
|
+
@s3_headers[:storage_class] = @options[:s3_storage_class] if @options[:s3_storage_class]
|
117
|
+
|
118
|
+
unless @options[:url].to_s.match(/^:s3.*url$/) || @options[:url] == ":asset_host"
|
119
|
+
@options[:path] = @options[:path].gsub(/:url/, @options[:url]).gsub(/^:rails_root\/public\/system/, '')
|
120
|
+
@options[:url] = ":s3_path_url"
|
99
121
|
end
|
122
|
+
@options[:url] = @options[:url].inspect if @options[:url].is_a?(Symbol)
|
100
123
|
|
101
|
-
|
102
|
-
:access_key_id => s3_credentials[:access_key_id],
|
103
|
-
:secret_access_key => s3_credentials[:secret_access_key]
|
104
|
-
))
|
124
|
+
@http_proxy = @options[:http_proxy] || nil
|
105
125
|
end
|
106
126
|
Paperclip.interpolates(:s3_alias_url) do |attachment, style|
|
107
127
|
"#{attachment.s3_protocol(style)}://#{attachment.s3_host_alias}/#{attachment.path(style).gsub(%r{^/}, "")}"
|
@@ -118,27 +138,61 @@ module Paperclip
|
|
118
138
|
end
|
119
139
|
|
120
140
|
def expiring_url(time = 3600, style_name = default_style)
|
121
|
-
|
141
|
+
if path
|
142
|
+
s3_object(style_name).url_for(:read, :expires => time, :secure => use_secure_protocol?(style_name)).to_s
|
143
|
+
end
|
122
144
|
end
|
123
145
|
|
124
146
|
def s3_credentials
|
125
|
-
@s3_credentials ||= parse_credentials(@options
|
147
|
+
@s3_credentials ||= parse_credentials(@options[:s3_credentials])
|
126
148
|
end
|
127
149
|
|
128
150
|
def s3_host_name
|
129
|
-
@options
|
151
|
+
@options[:s3_host_name] || s3_credentials[:s3_host_name] || "s3.amazonaws.com"
|
130
152
|
end
|
131
153
|
|
132
154
|
def s3_host_alias
|
133
|
-
@s3_host_alias = @options
|
155
|
+
@s3_host_alias = @options[:s3_host_alias]
|
134
156
|
@s3_host_alias = @s3_host_alias.call(self) if @s3_host_alias.is_a?(Proc)
|
135
157
|
@s3_host_alias
|
136
158
|
end
|
137
159
|
|
138
160
|
def bucket_name
|
139
|
-
@bucket = @options
|
161
|
+
@bucket = @options[:bucket] || s3_credentials[:bucket]
|
140
162
|
@bucket = @bucket.call(self) if @bucket.is_a?(Proc)
|
141
|
-
@bucket
|
163
|
+
@bucket or raise ArgumentError, "missing required :bucket option"
|
164
|
+
end
|
165
|
+
|
166
|
+
def s3_interface
|
167
|
+
@s3_interface ||= begin
|
168
|
+
config = { :s3_endpoint => s3_host_name }
|
169
|
+
|
170
|
+
if using_http_proxy?
|
171
|
+
|
172
|
+
proxy_opts = { :host => http_proxy_host }
|
173
|
+
proxy_opts[:port] = http_proxy_port if http_proxy_port
|
174
|
+
if http_proxy_user
|
175
|
+
userinfo = http_proxy_user.to_s
|
176
|
+
userinfo += ":#{http_proxy_password}" if http_proxy_password
|
177
|
+
proxy_opts[:userinfo] = userinfo
|
178
|
+
end
|
179
|
+
config[:proxy_uri] = URI::HTTP.build(proxy_opts)
|
180
|
+
end
|
181
|
+
|
182
|
+
[:access_key_id, :secret_access_key].each do |opt|
|
183
|
+
config[opt] = s3_credentials[opt] if s3_credentials[opt]
|
184
|
+
end
|
185
|
+
|
186
|
+
AWS::S3.new(config.merge(@s3_options))
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def s3_bucket
|
191
|
+
@s3_bucket ||= s3_interface.buckets[bucket_name]
|
192
|
+
end
|
193
|
+
|
194
|
+
def s3_object style_name = default_style
|
195
|
+
s3_bucket.objects[path(style_name).sub(%r{^/},'')]
|
142
196
|
end
|
143
197
|
|
144
198
|
def using_http_proxy?
|
@@ -178,7 +232,7 @@ module Paperclip
|
|
178
232
|
|
179
233
|
def exists?(style = default_style)
|
180
234
|
if original_filename
|
181
|
-
|
235
|
+
s3_object(style).exists?
|
182
236
|
else
|
183
237
|
false
|
184
238
|
end
|
@@ -207,30 +261,31 @@ module Paperclip
|
|
207
261
|
basename = File.basename(filename, extname)
|
208
262
|
file = Tempfile.new([basename, extname])
|
209
263
|
file.binmode
|
210
|
-
file.write(
|
264
|
+
file.write(s3_object(style).read)
|
211
265
|
file.rewind
|
212
266
|
return file
|
213
267
|
end
|
214
268
|
|
215
269
|
def create_bucket
|
216
|
-
|
270
|
+
s3_interface.buckets.create(bucket_name)
|
217
271
|
end
|
218
272
|
|
219
273
|
def flush_writes #:nodoc:
|
220
274
|
@queued_for_write.each do |style, file|
|
221
275
|
begin
|
222
276
|
log("saving #{path(style)}")
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
277
|
+
acl = @s3_permissions[style] || @s3_permissions[:default]
|
278
|
+
acl = acl.call(self, style) if acl.respond_to?(:call)
|
279
|
+
write_options = {
|
280
|
+
:content_type => file.content_type.to_s.strip,
|
281
|
+
:acl => acl
|
282
|
+
}
|
283
|
+
write_options[:metadata] = @s3_metadata unless @s3_metadata.empty?
|
284
|
+
write_options.merge!(@s3_headers)
|
285
|
+
s3_object(style).write(file, write_options)
|
286
|
+
rescue AWS::S3::Errors::NoSuchBucket => e
|
230
287
|
create_bucket
|
231
288
|
retry
|
232
|
-
rescue AWS::S3::ResponseError => e
|
233
|
-
raise
|
234
289
|
end
|
235
290
|
end
|
236
291
|
|
@@ -243,8 +298,8 @@ module Paperclip
|
|
243
298
|
@queued_for_delete.each do |path|
|
244
299
|
begin
|
245
300
|
log("deleting #{path}")
|
246
|
-
|
247
|
-
rescue AWS::
|
301
|
+
s3_bucket.objects[path.sub(%r{^/},'')].delete
|
302
|
+
rescue AWS::Errors::Base => e
|
248
303
|
# Ignore this.
|
249
304
|
end
|
250
305
|
end
|
@@ -265,6 +320,18 @@ module Paperclip
|
|
265
320
|
end
|
266
321
|
private :find_credentials
|
267
322
|
|
323
|
+
def establish_connection!
|
324
|
+
@connection ||= AWS::S3::Base.establish_connection!( @s3_options.merge(
|
325
|
+
:access_key_id => s3_credentials[:access_key_id],
|
326
|
+
:secret_access_key => s3_credentials[:secret_access_key]
|
327
|
+
))
|
328
|
+
end
|
329
|
+
private :establish_connection!
|
330
|
+
|
331
|
+
def use_secure_protocol?(style_name)
|
332
|
+
s3_protocol(style_name) == "https"
|
333
|
+
end
|
334
|
+
private :use_secure_protocol?
|
268
335
|
end
|
269
336
|
end
|
270
337
|
end
|