Unable to render images in view (paperclip/AWS) - ruby-on-rails

I have been scouring through SO posts for the last day and a half, and have asked another question related to this issue here, and have yet to come up with a solution. I am unable to render my images, which are being correctly uploaded to AWS in my view using <%= image_tag #user.avatar.url(:medium) %> as specified in the documentation.
Looking in my DB, all of the fields related to the avatar are indeed populated with:
avatar_file_name => meditation.jpg
avatar_content_type => image/jpeg
avatar_file_size => 109992
avatar_updated_at => 2016-08-04 06:48:31.361434
and the image can be viewed in the browser by double clicking on the image's link in my amazon bucket: https://s3.amazonaws.com/giving-tree-images/Users/sgau677/giving_tree/public/avatars/12/medium/meditation.jpg.jpg
As you can see, for some reason a double file extension is being appended, which is a separate issue (that I welcome feedback on) but which does not seem to be the issue, as I am not able to render in the view uploaded images with a single file extension either.
So with the images being uploaded, the db fields being populated, and no errors - I am at a loss as to why I cannot render them in the view. I suspect the issue is either 1) the path -which looks like this in my model:
has_attached_file :avatar,
:styles => { medium: "300x300#", thumb: "100x100#" },
:convert_options => {
:thumb => "-quality 75 -strip" },
:s3_host_name => "s3.amazonaws.com",
:path => ":rails_root/public/:attachment/:id/:style/:filename.:extension",
:url => ":attachment/:id/:style/:filename.:extension",
:default_url => "default_img.png",
:storage => :s3,
:s3_credentials => {
:bucket => 'giving-tree-images',
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
},
:s3_permissions => {
:original => 'public-read'
}
validates_attachment_content_type :avatar, content_type: /\Aimage\/.*\Z/
attr_accessor :avatar_file_name, :avatar_content_type, :avatar_file_size, :avatar_updated_at
Which as you can see seems to be correct (unless I should be taking out the :rails_root bit in my model?)
or 2) I need to somehow save the location of the images in a separate model (which I have seen other ppl do, but am not sure it is required, as others seem not to have done this - granted they may just not have mentioned that they did). This being a step has not been in any of the docs I have read however.
3) I also wonder if there is possibly a separate process that I need to be doing in development as opposed to production?
or 4) I am using rails 4.2.3 and have read in comments that paperclip does not support versions of aws > 2.00 - however the Heroku docs - instructed to use 2.3...so perhaps this is the issue?
gem "paperclip", "~> 5.0.0"
gem 'aws-sdk', '~> 2.3'
I have also set up, in following other posts, a config/asw.yml file that looks like this:
development:
access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %>
secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %>
production:
access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %>
secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %>
although I am not sure it is being read (where the ENV var's are stored in secrets.yml, as well as both locally and on heroku via terminal) and a config/s3.yml file that looks like this:
include 'secrets.yml'
development:
access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %>
secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %>
bucket: <%= ENV["S3_BUCKET_NAME"]%>
production:
access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %>
secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %>
bucket: <%= ENV["S3_BUCKET_NAME"]%>
an initializers/s3.rb
if Rails.env == "production"
# set credentials from ENV hash
S3_CREDENTIALS = { :access_key_id => ENV['AWS_ACCESS_KEY_ID'], :secret_access_key => ENV['AWS_SECRET_ACCESS_KEY'], :bucket => "giving-tree-images"}
else
# get credentials from YML file
S3_CREDENTIALS = Rails.root.join("config/s3.yml")
end
and modified my both environments/development.rb and my environments/production.rb to include:
config.paperclip_defaults = {
storage: :s3,
:s3_host_name => "s3.amazonaws.com",
s3_credentials: {
bucket: ENV.fetch('S3_BUCKET_NAME'),
access_key_id: ENV.fetch('AWS_ACCESS_KEY_ID'),
secret_access_key: ENV.fetch('AWS_SECRET_ACCESS_KEY'),
s3_region: ENV.fetch('AWS_REGION'),
}
}
...as per multiple other posts combined suggested. It is quite possible I do not need all of this, so if anyone can help as to what I should be getting rid of, and why I cannot render images in the view - I would REALLY appreciate it as this is maddening.

You are putting extension after :filename for both the :path and the :url -- but you shouldn't.
:filename includes the extension. That is why you are getting the extension twice.
You have this in your model:
:path => ":rails_root/public/:attachment/:id/:style/:filename.:extension",
:url => ":attachment/:id/:style/:filename.:extension",
and after you remove .:extension, you should have this:
:path => ":rails_root/public/:attachment/:id/:style/:filename",
:url => ":attachment/:id/:style/:filename",

Related

`fetch': key not found: "S3_BUCKET_NAME" (KeyError) with paperclip/aws s3/rails

I am getting a 'fetch': key not found: "S3_BUCKET_NAME" (KeyError) error in rails (4.2.3) using 'aws-sdk', '~> 2.3' and "paperclip", "~> 5.0.0"
I have set the Keys in my environment via terminal and running heroku config shows them listed.
In both my config/environments/development.rb as well as in my config production.rb I have included:
config.paperclip_defaults = {
storage: :s3,
s3_credentials: {
bucket: ENV.fetch('S3_BUCKET_NAME'),
access_key_id: ENV.fetch('AWS_ACCESS_KEY_ID'),
secret_access_key: ENV.fetch('AWS_SECRET_ACCESS_KEY'),
s3_region: ENV.fetch('AWS_REGION'),
}
}
I have also included the above code in my user.rb model, but for the sake of reference it looks like this in the model:
has_attached_file :avatar,
styles: { medium: "300x300#", thumb: "100x100#" },
:convert_options => {
:thumb => "-quality 75 -strip" },
: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'],
:region => ENV['AWS_REGION']
},
:path => ":filename.:extension",
# :path => ":rails_root/public/system/:attachment/:id/:style/:filename",
:default_url => "default_img.png"
validates_attachment_content_type :avatar, content_type: /\Aimage\/.*\Z/
I have also included the env vars in my secrets.yml:
development:
secret_key_base: 817c07d41b8524495628fbe91fb1f0535ade65aa96a3fee379a8d16c29cc1f7b167f537442e547422ab17ee9700028a95896eb1c0717de06dfe7895d15ddb5ce
secret_key: sk_test_xxx
publishable_key: pk_test_xxx
access_key_id: xxx
secret_access_key: xxx
s3_bucket_name: 'bucket-name'
test:
secret_key_base: a38e71848a4d9bc63fa8dce4522add10a4931b10e6786f0cab6a9eb1643e271b992f52fa6eff672b0d03687003099c0632477dd26b246ac4e637c52c69ec4ab0
# Do not keep production secrets in the repository,
# instead read values from the environment.
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
secret_key: <%= ENV["SECRET_KEY"] %>
publishable_key: <%= ENV["PUBLISHABLE_KEY"] %>
access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %>
secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %>
s3_bucket_name: <%= ENV["S3_BUCKET_NAME"]%>
although that may not have been required. Googling around and going through the few other posts on SO related to this error have given me little to go on - does anybody have any ideas on what the issue may be?
'fetch': key not found: "S3_BUCKET_NAME" means that the environment variables S3_BUCKET_NAME does not have a value.
In your case you are using Heroku. Follow the instructions in the link below.
For Heroku: https://devcenter.heroku.com/articles/config-vars.
If you are using ENV['variables'] you need to have them set in every environment. test, production and development. If you are developing on a PC, MAC, or Linux you need to make sure the environment variables are set.
For linux:
https://www.digitalocean.com/community/tutorials/how-to-read-and-set-environmental-and-shell-variables-on-a-linux-vps
For OSX:
I do it the same was as linux, I just set them in my ~/.zshrc by adding a line like this. If you aren't using zshell then add a line to your ~/.bashrc or ~/.bash_profile.
export ENV_VARIABLE_NAME="value"
For Windows:
I don't know how, but I am sure google does.

AWS::S3::Errors::NoSuchKey No Such Key

I have a Rails 4 app with Paperclip running on Heroku. I recently started encountering a problem that is preventing me from updating any models with attached images. For example, any time I make a change through my site's CMS system to my Company model, the changes are not saved. I've tried changing only the image, the image and various other attributes, and only non-image attributes. It's as if the #company.save is never called in my controller's update action.
I found this issue report and tried the various solutions suggested, but nothing worked.
Here is my Company model:
class Company < ActiveRecord::Base
has_attached_file :logo, :styles => { :medium => "300x300>", :thumb => "100x100>" }
validates_attachment_content_type :logo, :content_type => /\Aimage\/.*\Z/
end
In my logs, I get the following error:
[AWS S3 404 0.022711 0 retries] head_object(:bucket_name=>"myApp",:key=>"companies/profile_photos/000/000/118/original/2015-09-05_19.05.34.jpg") AWS::S3::Errors::NoSuchKey No Such Key
I verified that my S3 credentials are set using heroku config and that they are valid.
I'm not certain, but I suspect that this may have something to do with my recent addition of the following buildpacks:
=== myApp Buildpack URLs
1. https://github.com/bobbus/image-optim-buildpack.git
2. https://github.com/heroku/heroku-buildpack-ruby.git
I've not been able to reproduce the problem on localhost.
Update
I've since opened up an issue report on this problem.
Here is my config.paperclip_defaults block in production.rd
config.paperclip_defaults = {
:storage => :s3,
:s3_protocol => :https,
:s3_host_name => 's3.amazonaws.com',
:s3_credentials => {
:bucket => ENV['S3_BUCKET_NAME'],
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
}
}
Here is my aws.yml:
development:
access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %>
secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %>
production:
access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %>
secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %>
Documentation from the GitHub paperclip wiki
Assuming you are using dotenv-rails...
In development.rb and production.rb files:
config.paperclip_defaults = {
storage: :s3,
s3_host_name: ENV['S3_HOST_NAME'],
bucket: ENV['S3_BUCKET_NAME']
}
Make sure to set these variables in your Heroku environment:
$ heroku config:set S3_HOST_NAME=your-s3-hostname-here S3_BUCKET_NAME=your-production-bucket-name-here
Paperclip-with-Amazon-S3
Documentation from rubydoc.info
This states you should have a yaml file with these details specified or write a method on your model.
rubydoc.info Paperclip::Storage::S3
No Such Key is S3's way of saying "404 Not Found."
I don't believe it has any alternate meanings.
The request was authorized and syntactically valid, but there's no file in the bucket at the specified path.
You may want to inspect the contents of your bucket from the AWS console.

Rails 4, Paperclip, Amazon S3 Config Amazon Path

I'm trying to configure the endpoint which is returned from paperclip when my object is successfully uploaded to Amazon's S3 service. The upload and everything is working correctly, but the URL that is being returned is incorrect for displaying the upload.
Right now, the url that is being returned is http://s3.amazonaws.com/path/to/my/items (as seen in the picture below).
Instead of s3.amazonaws.com, I would like the root to be specific to the bucket's location (e.g. s3-us-west-1.amazonaws.com/path/to/my/items)
Where should I try and configure a different url path (from s3.amazonaws.com to something else)? I've tried to add a url with the above path into my configuration file like:
#Paperclip Amazon S3
config.paperclip_defaults = {
:storage => :s3,
:url => "https://s3-us-west-1.amazonaws.com/",
:s3_credentials => {
:bucket => ENV['S3_BUCKET_NAME'],
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
}
}
Which did not appear to have any effect. Please advise on where I should be setting this option!
Thanks in advance!
If you're going to use S3, we've found that you have to include the S3 credentials in your actual model (not just the config files). Here's what we do:
Model
#Image Upload
Paperclip.options[:command_path] = 'C:\RailsInstaller\ImageMagick'
has_attached_file :image,
:styles => { :medium => "x300", :thumb => "x100" },
:default_url => "****",
:storage => :s3,
:bucket => '****',
:s3_credentials => S3_CREDENTIALS,
:url => "/:image/:id/:style/:basename.:extension",
:path => ":image/:id/:style/:basename.:extension"
config/application.rb
# Paperclip (for Amazon) (we use EU servers)
config.paperclip_defaults = {
:storage => :s3,
:s3_host_name => 's3-eu-west-1.amazonaws.com'
}
config/s3.yml
#Amazon AWS Config
development:
access_key_id: **********
secret_access_key: **************
bucket: ****
production:
access_key_id: ***********
secret_access_key: ***********
bucket: ****
Hope this helps?
I also had the same problem when migrating to Spree 2.2 and am still not sure how to solve it the correct way. It seems like Paperclip should have been updating the path from the configuration, but it isn't.
Lacking a better solution, I've overridden the Spree::Image class like this:
1 Spree::Image.class_eval do
2 has_attached_file :attachment,
3 styles: { mini: '48x48>', small: '100x100>', product: '240x240>', large: '600x600>' },
4 default_style: :product,
5 url: '/spree/products/:id/:style/:basename.:extension',
6 path: 'products/:id/:style/:basename.:extension',
7 convert_options: { all: '-strip -auto-orient -colorspace sRGB' }ยท
8 end
After some experimentation I have found that setting :s3_host_name globally suffices. I ended up with the same problem because I was setting :s3_region, which was being used by Paperclip (post-4.3.1, with aws-sdk 2) for storing attachments, but not when generating the URLs.
This may also be of interest to readers who end up on this problem: https://github.com/thoughtbot/paperclip/wiki/Restricting-Access-to-Objects-Stored-on-Amazon-S3

paperclip working in development but not working in production?

I'm pretty new to rails and seem to be having an issue with the paperclip gem. I installed the gem and it works well in development (localhost:3000) but when I'm running it on the heroku server, for some reason it does not want to attach files, and the app breaks (error 500 page).
Here is the process i ran... I pushed my file to heroku, heroku ran rake db:migrate (to add paperclip migrations), and then I ran heroku restart (to restart the app with new migrations). This did not seem to help.
Here is the code that I have for paperclip:
user.rb model:
has_attached_file :avatar,
:styles => {:small => "70x70>"},
:url => "/users/:attachment/:id/:style/:basename.:extension",
:path => ":rails_root/public/users/:attachment/:id/:style/:basename.:extension"
validates_attachment_size :avatar, :less_than => 500.kilobytes
validates_attachment_content_type :avatar, :content_type => ['image/jpeg', 'image/png']
edit_form.html.haml view:
= form_for (#user || User.new), :html => { :multipart => true } do |f|
...
.profile_picture.text_field
= image_tag current_profile.avatar.url(:small)
%br
= f.file_field :avatar
Again, for some reason it runs great in development, but breaks down in production. Any pointers would be greatly appreciated... I just cant seem to figure this out and it's pretty frustrating. Thank you so much for your time and any help!
In your model.
has_attached_file :picture,
:styles => {:large => "275x450>"},
:storage => :s3,
:s3_credentials => "#{RAILS_ROOT}/config/s3.yml",
:path => "appname/:attachment/:style/:id.:extension"
In s3.yml in your config dir:
development:
bucket: bucketname
access_key_id: key
secret_access_key: key
production:
bucket: bucketname
access_key_id: key
secret_access_key: key
Then go signup for a bucket at Amazon S3: http://aws.amazon.com/s3/
You could be having a few problems. However, the first is that you can not write to the file system on Heroku. You will have to implement a different storage mechanism such as s3. You can read about this limitation here: http://devcenter.heroku.com/articles/read-only-filesystem

heroku+s3+paperclip

Guys,
I'm having a problem with s3...I'm trying to configure the s3 this way to work with the paperclip:
has_attached_file :photo,
:storage => :s3,
:bucket => 'gallerybucket',
:styles => { :small => ["150", :png], :large => ["500", :png], :very_large => ['750x500>', :png] },
:path => ":rails_root/public/images/:class/:attachment/:id/:style_:basename.png",
:url => "/images/:class/:attachment/:id/:style_:basename.png",
:default_url => "/images/sem_imagem.gif",
:s3_credentials => {
:access_key_id => ENV['ac'],
:secret_access_key => ENV['sc']
}
but it always shows me this error. I don't understand what I'm doing wrong here. Is there some configuration missing?
If you don't have an s3 account already go get one here:
http://aws.amazon.com/s3/
You need to add this to your contact model:
app/models/contact.rb
has_attached_file :picture,
:styles => {:large => "275x450>"},
:storage => :s3,
:s3_credentials => "#{RAILS_ROOT}/config/s3.yml",
:path => "appname/:attachment/:style/:id.:extension"
Make sure you appname is your rails app name on heroku. And make sure you rename picture to whatever you have named your picture.
Then you need a config file in config/s3.yml.
development:
bucket: bucked_name
access_key_id: key
secret_access_key: secret
production:
bucket: bucked_name
access_key_id: key
secret_access_key: secret
Make sure you get the key and secret correct.
In your gem file make sure you have these gems install :
gem "aws-s3", :require => "aws/s3"
gem "paperclip"
Sounds like you added the variables to you heroku account, but did you add them to your .bashrc file?
export ACCESS_KEY_ID='acckeyid'
export SECRET_ACCESS_KEY='secacckey'
Then in your code:
:s3_credentials => {
:access_key_id => ENV['ACCESS_KEY_ID'],
:secret_access_key => ENV['SECRET_ACCESS_KEY']
}
I have a blog post I wrote that talks about this a little as well.

Resources