Reputation: 1323
I've got a Site model which allows for a background_image upload to S3 via Paperclip. Where it gets weird is that each Site has it's own S3 credentials store in it's model. My question is this, how can I reference the site's own attributes when uploading via Paperclip?
class Site < ActiveRecord::Base
attr_accessible :background_image,
:s3_access_key_id,
:s3_secret_access_key,
:s3_username
has_attached_file :background_image,
storage: :s3,
s3_credentials: {
access_key_id: @s3_access_key_id.to_s,
secret_access_key: @s3_secret_access_key.to_s
},
bucket: "my-app",
s3_permissions: "public-read",
path: "/home/#{@s3_username}/background_images/:id/:filename"
end
Unfortunately with this setup I just get The AWS Access Key Id you provided does not exist in our records
. I assume it's just getting blank values because it works fine when I hard-code the values from the database.
Upvotes: 2
Views: 899
Reputation: 6714
Your problem here is that has_attached_file
is a being called on the Site
class when site.rb
is first read, not on the site instance. Fortunately, paperclip supports dynamic configuration in several places, wherein you can retrieve the Site
instance at runtime. Try this instead:
has_attached_file :background_image,
s3_credentials: lambda { |attachment| attachment.instance.s3_keys },
path: lambda { |attachment| "/home/#{attachment.instance.s3_username}/background_images/:id/filename" }
def s3_keys
{
access_key_id: self.s3_access_key_id.to_s,
secret_access_key: self.s3_secret_access_key.to_s
}
end
Those lambdas will get evaluated at runtime, with the Paperclip::Attachment
object passed in as a param. You can retrieve the Site
instance with Paperclip::Attachment#instance
. So then you can call methods on the instance to get its specific keys.
You can also use a more specific/advanced trick for getting the s3_username
into the path. You can just teach paperclip more path name interpolations. Like you could add a file at config/initializers/paperclip.rb
with:
Paperclip.interpolates :s3_username do |attachment, style|
attachment.instance.s3_username
end
and then your Site
model could look like
has_attached_file :background_image,
s3_credentials: lambda { |attachment| attachment.instance.s3_keys },
path: "/home/:s3_username/background_images/:id/:filename"
def s3_keys
{
access_key_id: self.s3_access_key_id.to_s,
secret_access_key: self.s3_secret_access_key.to_s
}
end
Upvotes: 3