using Amazon S3 with the paperclip gem - ruby-on-rails

Is it good practice to simply post my access key id/secret access key directly into the model? For example...
has_attached_file :pic, :s3_credentials => {
:bucket => 'MY_BUCKET_NAME',
:path => ":rails_root/public/system/:attachment/:id/:style/:filename",
:url => "/system/:attachment/:id/:style/:filename",
:access_key_id => "12345Secret#blahblah",
:secret_access_key => "12345###"
}
This actually works, however, when I duplicate the image to another model...it doesnt upload.
i.e. #other_user.pic = #user.pic (to copy the image to the other User)
For instance if the image that works is: S3Amazon/pic/01.working.jpg
the copied image has a one number increase in the file like so: S3Amazon/pic/02.working.jpg
This image does not open, been searching all week for a way to make this work.

Try
#other_user.pic = #user.pic
#other_user.save!
And make sure, if you're doing this from the console, that you do #other_user.reload before checking urls

Related

set up paperclip with amazon s3

I am trying to set up the paperclip with amazon s3, I have found a tutorial which is like the following code. What do I have to put as a url and path ?
config.paperclip_defaults = {
:storage => :s3,
:s3_credentials => {
:bucket => ENV['S3_BUCKET_NAME'],
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
},
:url => ':s3_domain_url',
:path => "/:class/:attachment/:id_partition/:style/:filename"
}
You don't have to worry about touching url, unless you care about whether or not the URL is placed domain-style (bucket-name.s3.amazonaws) or path-style (s3.amazonaws.com/bucket-name). You could not add that in your configurations and it will default to domain-style.
Path tells Paperclip what path to save your attachments. This means in local file system, it will save it under "(model's name)/(attachment name)/(id)/(style e.g. small, thumbnail)/(file name)." It will do the same thing for your bucket, so you'll have all these fun folders to click through if you view your physical bucket. You're free to leave it to the default, or change it if you want your path to be a little shorter.

Paperclip is not generating url properly for CNAME

I'm tying to get a cloudfront distribution wired up with a custom domain to paperclip but it's not generating my url properly. Here is my configuration:
# initializers/paperclip_defaults.rb
Paperclip::Attachment.default_options.merge!({
:storage => :s3,
:s3_credentials => "#{Rails.root}/config/amazon_s3.yml",
:bucket => "my-image-bucket",
:path => "production/attachments/:attachment/:id/:style/:basename.:extension",
:url => ":s3_host_alias",
:s3_headers => {'Cache-Control' => 'max-age=2147483648'},
:s3_protocol => :https,
:s3_host_alias => "cdn.mydomain.com",
})
According to the docs and every blog post I've read this should be correct. The problem is that it winds up generating this:
https://s3.amazonaws.com/my-image-bucket/production/products/images/44/original/my-image.jpg
The only way I've gotten it to use the CNAME is by specifying s3_host_name which according to the documentation is only used for the Tokyo region. And this also breaks uploads. Any ideas as to what I'm doing wrong?
I'm using Paperclip 3.5.2.
UPDATE
I'm debugging inside attachment.rb#url and here's what I'm seeing. Paperclip::Attachment.default_options[:url] returns cdn.mydomain.com which is correct. However, #options[:url] is returning :s3_path_url instead of s3_host_alias. For some reason that default option is not being merged in properly. However the s3_host_alias option is since #options[:s3_host_alias] is returning cdn.mydomain.com as expected.
So it turns out that :s3_alias_url is the correct token to use for the url and not :s3_host_alias. Not sure where that's documented though. Had to look at s3.rb to figure it out.

Ruby on Rails 4 - Paperclip AWS Image URL is wrong?

I've used paperclip and AWS together before, but I just created this Rails 4 app, and my image.url method is showing looking for the image at 'http://s3.amazonaws.com/', when it should be looking for them at 's3-us-west-2.amazonaws.com'. I'm assuming this is because the region for the first account is US Standard, whereas the new one is Oregon.
Any way for me to change the region in the config files or something?
Apparently there used to be a bunch of workarounds for this, but now there is an option in the config called s3_host_name.
ExampleApp:Application.configure do
config.paperclip_defaults = {
:storage => :s3,
:s3_host_name => 's3-us-west-2.amazonaws.com',
:s3_credentials => {
:bucket => '#',
:access_key_id => '#',
:secret_access_key => '#'
}
}
end

Rails3 - how to get at aws-s3's yml config data in the app?

Specifically, i have a file config/amazon_s3.yml which is used by the aws-s3 gem to set up some s3 config settings like secret keys etc. I also write some of this data into a var in ENV in a different file in initializers so i can reference them in calls to the "has_attached_file" method used by paperclip.
It would be smarter to get the file in initializers to read them out of the s3 config yml, or some config settings for the classes used by the gem, eg something like AWS::S3::Base.connection.secret_access_key (this doesn't work).
Any ideas?
I found the answer here How to use YML values in a config/initalizer
First i load in the yaml in and stick it in a constant.
#config/initializers/constants.rb
S3_CONFIG = YAML.load_file("#{::Rails.root}/config/amazon_s3.yml")
Then, when i set up paperclip for a model, pull in these values, making sure i refer to the current environment:
class Entry < ActiveRecord::Base
has_attached_file :media,
:styles => {
:medium => "300x300>",
:thumb => "110x110>"
},
:storage => :s3,
:bucket =>S3_CONFIG[::Rails.env]["bucket"],
:s3_credentials => {
:access_key_id => S3_CONFIG[::Rails.env]["access_key_id"],
:secret_access_key => S3_CONFIG[::Rails.env]["secret_access_key"]
}
end

Rails user-conditional statement in model

I'm working on a Rails app using attachment_ fu and Amazon S3 storage. Is it possible to make the :s3_ access (a part of the has_attachment options) conditional based on a user input when creating the object. I would like the user to be able if to select if the attachment is authenticated-read or public-read. Is this possible and how would you setup the conditional statement?
My model looks like this:
has_attachment :content_type => :image,
:storage => :s3,
:size => 0.kilobytes..6144.kilobytes,
:processor => 'Rmagick',
:resize_to => '650x500>',
:thumbnails => { :thumb => '75x75!' },
:s3_access => ( [[conditional]] ? 'authenticated-read' : 'public-read' )
Obviously [[conditional]] is what I'm looking to replace, but I don't know how to correctly setup a conditional for the item based off user action in the model. Maybe this is the wrong time of conditional for this type statement. Any suggestions?
James, I've done this before. I was digging through my old code, trying to find a sample I could show here, but I can't seem to find it. Old client, code is probably gone, etc...
You are on the right track though. Remember, 'has_attachment' is just a method call with a hash for the parameters, so if you treat it as such, you can adjust which hash values are ultimately sent to the method.
Edit - Here is a code sample -
production = ENV['RAILS_ENV'] == 'production'
has_attachment :content_type => :image,
:max_size => 1.megabyte,
:resize_to => '800x600>',
:thumbnails => { :thumb => '146x146>', :small => '75x75' },
# skip s3 for local development and testing
:storage => (production ? :s3 : :file_system),
:path_prefix => (production ? 'comment_images' : 'public/comment_images')
In the above example, I wanted to store uploads locally while developing, but switch to S3 when in production. So you are very close to where you need to be...

Resources