Commit 5fa9db4d by jaredmoody Committed by Jon Yurek

Support per style options for s3 storage class

parent b2d9a1a9
...@@ -102,6 +102,14 @@ module Paperclip ...@@ -102,6 +102,14 @@ module Paperclip
# Redundancy Storage. RRS enables customers to reduce their # Redundancy Storage. RRS enables customers to reduce their
# costs by storing non-critical, reproducible data at lower # costs by storing non-critical, reproducible data at lower
# levels of redundancy than Amazon S3's standard storage. # levels of redundancy than Amazon S3's standard storage.
#
# You can set storage class on a per style bases by doing the following:
# :s3_storage_class => {
# :thumb => :reduced_reduncancy
# }
# Or globally:
# :s3_storage_class => :reduced_redundancy
module S3 module S3
def self.extended base def self.extended base
begin begin
...@@ -139,7 +147,7 @@ module Paperclip ...@@ -139,7 +147,7 @@ module Paperclip
@s3_headers = {} @s3_headers = {}
merge_s3_headers(@options[:s3_headers], @s3_headers, @s3_metadata) merge_s3_headers(@options[:s3_headers], @s3_headers, @s3_metadata)
@s3_headers[:storage_class] = @options[:s3_storage_class] if @options[:s3_storage_class] @s3_storage_class = set_storage_class(@options[:s3_storage_class])
@s3_server_side_encryption = :aes256 @s3_server_side_encryption = :aes256
if @options[:s3_server_side_encryption].blank? if @options[:s3_server_side_encryption].blank?
...@@ -272,6 +280,11 @@ module Paperclip ...@@ -272,6 +280,11 @@ module Paperclip
permissions.merge :default => (permissions[:default] || :public_read) permissions.merge :default => (permissions[:default] || :public_read)
end end
def set_storage_class(storage_class)
storage_class = {:default => storage_class} unless storage_class.respond_to?(:merge)
storage_class
end
def parse_credentials creds def parse_credentials creds
creds = creds.respond_to?('call') ? creds.call(self) : creds creds = creds.respond_to?('call') ? creds.call(self) : creds
creds = find_credentials(creds).stringify_keys creds = find_credentials(creds).stringify_keys
...@@ -295,6 +308,10 @@ module Paperclip ...@@ -295,6 +308,10 @@ module Paperclip
s3_permissions s3_permissions
end end
def s3_storage_class(style = default_style)
@s3_storage_class[style] || @s3_storage_class[:default]
end
def s3_protocol(style = default_style, with_colon = false) def s3_protocol(style = default_style, with_colon = false)
protocol = @s3_protocol protocol = @s3_protocol
protocol = protocol.call(style, self) if protocol.respond_to?(:call) protocol = protocol.call(style, self) if protocol.respond_to?(:call)
...@@ -320,6 +337,11 @@ module Paperclip ...@@ -320,6 +337,11 @@ module Paperclip
:content_type => file.content_type, :content_type => file.content_type,
:acl => acl :acl => acl
} }
# add storage class for this style if defined
storage_class = s3_storage_class(style)
write_options.merge!(:storage_class => storage_class) if storage_class
if @s3_server_side_encryption if @s3_server_side_encryption
write_options[:server_side_encryption] = @s3_server_side_encryption write_options[:server_side_encryption] = @s3_server_side_encryption
end end
......
...@@ -938,40 +938,130 @@ describe Paperclip::Storage::S3 do ...@@ -938,40 +938,130 @@ describe Paperclip::Storage::S3 do
end end
end end
context "An attachment with S3 storage and storage class set using the header name" do context "An attachment with S3 storage and storage class set" do
before do context "using the header name" do
rebuild_model storage: :s3, before do
bucket: "testing", rebuild_model storage: :s3,
path: ":attachment/:style/:basename:dotextension", bucket: "testing",
s3_credentials: { path: ":attachment/:style/:basename:dotextension",
'access_key_id' => "12345", s3_credentials: {
'secret_access_key' => "54321" 'access_key_id' => "12345",
}, 'secret_access_key' => "54321"
s3_headers: { "x-amz-storage-class" => "reduced_redundancy" } },
s3_headers: { "x-amz-storage-class" => "reduced_redundancy" }
end
context "when assigned" do
before do
@file = File.new(fixture_file('5k.png'), 'rb')
@dummy = Dummy.new
@dummy.avatar = @file
end
after { @file.close }
context "and saved" do
before do
object = stub
@dummy.avatar.stubs(:s3_object).returns(object)
object.expects(:write).with(anything,
content_type: "image/png",
acl: :public_read,
storage_class: "reduced_redundancy")
@dummy.save
end
it "succeeds" do
assert true
end
end
end
end end
context "when assigned" do context "using per style hash" do
before do before do
@file = File.new(fixture_file('5k.png'), 'rb') rebuild_model :storage => :s3,
@dummy = Dummy.new :bucket => "testing",
@dummy.avatar = @file :path => ":attachment/:style/:basename.:extension",
:styles => {
:thumb => "80x80>"
},
:s3_credentials => {
'access_key_id' => "12345",
'secret_access_key' => "54321"
},
:s3_storage_class => {
:thumb => :reduced_redundancy
}
end end
after { @file.close } context "when assigned" do
before do
@file = File.new(fixture_file('5k.png'), 'rb')
@dummy = Dummy.new
@dummy.avatar = @file
end
context "and saved" do after { @file.close }
context "and saved" do
before do
object = stub
[:thumb, :original].each do |style|
@dummy.avatar.stubs(:s3_object).with(style).returns(object)
expected_options = {:content_type => "image/png", :acl => :public_read}
expected_options.merge!(:storage_class => :reduced_redundancy) if style == :thumb
object.expects(:write).with(anything, expected_options)
end
@dummy.save
end
it "succeeds" do
assert true
end
end
end
end
context "using global hash option" do
before do
rebuild_model :storage => :s3,
:bucket => "testing",
:path => ":attachment/:style/:basename.:extension",
:styles => {
:thumb => "80x80>"
},
:s3_credentials => {
'access_key_id' => "12345",
'secret_access_key' => "54321"
},
:s3_storage_class => :reduced_redundancy
end
context "when assigned" do
before do before do
object = stub @file = File.new(fixture_file('5k.png'), 'rb')
@dummy.avatar.stubs(:s3_object).returns(object) @dummy = Dummy.new
object.expects(:write).with(anything, @dummy.avatar = @file
content_type: "image/png",
acl: :public_read,
storage_class: "reduced_redundancy")
@dummy.save
end end
it "succeeds" do after { @file.close }
assert true
context "and saved" do
before do
object = stub
[:thumb, :original].each do |style|
@dummy.avatar.stubs(:s3_object).with(style).returns(object)
object.expects(:write).with(anything, :content_type => "image/png",
:acl => :public_read,
:storage_class => :reduced_redundancy)
end
@dummy.save
end
it "succeeds" do
assert true
end
end end
end end
end end
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment