AWS S3 integration yields undefined method `match' - ruby-on-rails

I'm working on a simple project using Paperclip to upload images. Everything has been working just fine until I attempted to integrate S3 with Paperclip. Upon 'uploading' a user's image I get a NoMethodError (undefined method 'match' for nil:NilClass): error. This only happens when I have my S3 configuration running - if I comment it out the file uploads perfectly.
My configuration:
development.rb:
....
....
config.paperclip_defaults = {
:storage => :s3,
:s3_credentials => {
:bucket => ENV['AWS_BUCKET_ID'],
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
}
}
My Model:
class User < ActiveRecord::Base
has_attached_file :image_file, default_url: "/myapp/images/:style/missing.png"
validates_attachment_file_name :image_file, matches: [/png\Z/, /jpeg\Z/, /tiff\Z/, /bmp\Z/, /jpg\Z/]
entire error output from console:
NoMethodError (undefined method `match' for nil:NilClass):
app/controllers/images_controller.rb:33:in `block in create'
app/controllers/images_controller.rb:32:in `create'
Things I tried:
I added the AWS keys and bucket name directly into the code instead
of as an environmental variable.
As mentioned above, I commented out the AWS configuration in my environment file and it seemed to work perfectly.
It's probably worth mentioning that I installed the fog gem earlier to start configuring for Google Cloud Storage, but decided to stick with S3 instead. I used gem uninstall fog to remove the gem but it appears some dependencies stayed behind.

Add :s3_region to your config map:
E.g.
config.paperclip_defaults = {
:storage => :s3,
:s3_credentials => {
:bucket => ENV['AWS_BUCKET_ID'],
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
},
:s3_region => ENV['AWS_REGION']
}
Unfortunately this is a v5.0.0 feature (in Beta). And therefore there's nothing about it in the docs. However there is a comment about it in the actual 5.0 code.
Also good to note that the s3_permissions key in papertrail expects a string value now (it used to accept symbols).
:s3_permissions => 'public-read'

You need to specify the region in you s3_credentials, in a way such as region: ENV["AWS_REGION"].
As for cleaning up unused gems you can run bundle clean.

Related

RoR AWS-SDK Error when accessing bucket in Europe region

I am using latest aws-sdk for Ruby. My rake file contains following line to connect to S3 bucket:
require 'aws-sdk'
...
AWS.config(
:access_key_id => 'xxxxx',
:secret_access_key => 'xxxxx'
)
s3 = AWS::S3.new
object = s3.buckets['bucket_in_ireland'].objects['data.csv']
When accessing an AWS S3 bucket in region US that works perfectly fine. But getting following error while accessing AWS S3 bucket in region Ireland:
AWS::S3::Errorrs::PermanentRedirect: The bucket you are attempting to access must be addressed using the specified endpoint. Please send all future requests to this endpoint.
From Google I could find two solutions:
Put AWS::S3::DEFAULT_HOST.replace "s3-eu-west-1.amazonaws.com" at the bottom of environment.rb
Set :s3_host_name => 's3-eu-west-1.amazonaws.com' for paperclip default settings
When I placed the line mentioned in (1) at the bottom of environment.rb, the error message changed to following:
NameError: uninitialized constant AWS::S3::DEFAULT_HOST
Then I tried (2) by updating following code in production.rb but that didn't help.
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'],
:s3_host_name => 's3-eu-west-1.amazonaws.com'
}
}
Note: Also tried to apply this fix [https://github.com/aws/aws-sdk-ruby/issues/510] but nothing really changed after modifications in environment.rb, but nothing work.
Any help please...
Setting s3_endpoint to AWS config solved the issue for me.
AWS.config(
:access_key_id => 'xxxx',
:secret_access_key => 'xxxx',
:s3_endpoint => 's3-eu-west-1.amazonaws.com'
)

Paperclip on heroku with S3 - not working

I am using paperclip to handle image uploads in my Rails app. All works fine running in the development environment locally using the File Storage.
Now I am trying to get this working using S3 (because the app is to run on Heroku). I have set up a bucket and set the appropriate parameters in development.rb and production.rb as per the instructions here: https://devcenter.heroku.com/articles/paperclip-s3
When I start the server, I get the following error:
/Users/ganzogo/.rvm/gems/ruby-1.9.3-p362/gems/railties-3.2.13/lib/rails/railtie/configuration.rb:85:in `method_missing': undefined method `paperclip' for #<Rails::Application::Configuration:0x007fcb8b952000> (NoMethodError)
from /Users/ganzogo/Documents/acknowledgement/true-rails/config/environments/development.rb:41:in `block in <top (required)>'
And then it crashes.
The line referred to in the error is:
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']
}
}
I get exactly the same error if I try to run on Heroku. Has anyone been through this and have any idea what I have missed?
It looks like you may have a typo in your configuration block. Try changing config.paperclip.defaults = {...} to config.paperclip_defaults = {...} and that should solve your problem.
We got this working on one of our live apps
The difference is you need to put the credentials into the model itself. Here's what we've got:
#app/models/image.rb
#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
#app/config/application.rb
config.paperclip_defaults = {
:storage => :s3,
:s3_host_name => 's3-eu-west-1.amazonaws.com'
}
In Heroku, you'll need to add the various environment variables to your config settings

Paperclip/heroku/S3 Configuration is setup as best as I can tell but getting error on upload

Here's the error I get when I try to upload an image through the live site:
ArgumentError (missing required :bucket option):
app/controllers/editions_controller.rb:53:in `block in create'
app/controllers/editions_controller.rb:52:in `create'
I have the latest versions of aws-sdk and paperclip
I've got the following in production.rb
config.paperclip_defaults = {
:storage => :s3,
:s3_credentials => {
:bucket => ENV['bucket_name'],
:access_key_id => ENV['key'],
:secret_access_key => ENV['key2']
}
I've got my AWS_BUCKET set on my heroku app:
AWS_BUCKET: bucket_name
S3_BUCKET_NAME: bucket_name
AWS_ACCESS_KEY_ID: key
AWS_SECRET_ACCESS_KEY: key2
Can anybody suggest why this isn't working? Thanks.
You've got:
:s3_credentials => {
:bucket => ENV['bucket_name']
}
I've always been told that you should capitalize the constants like so:
:s3_credentials => {
:bucket => ENV['BUCKET_NAME']
}
Additionally, you have not actually set an ENV variable called BUCKET_NAME on heroku, you have the following:
AWS_BUCKET: bucket_name
But if your env var is called BUCKET_NAME, then you need the following instead:
BUCKET_NAME: bucket_name
So from the commane line you'd want to run something like heroku config:set BUCKET_NAME=bucket_name
And finally, you've changed the names of your env vars from those that are suggested in the paperclip readme. You've gone with ENV['BUCKET_NAME'] when everyone else uses ENV['AWS_BUCKET']. I dunno if that will effect anything, but try using the process outlined here by heroku.
Try those changes and let me know how they work out. Good luck.

S3 / Paperclip working on Heroku but not Localhost

Paperclip works perfectly for my app on Heroku, but I can't seem to get it working locally. Every time I try to do something I get an "missing required :bucket option" ... but the bucket is there and it works on Heroku!
Here's my model if it helps:
has_attached_file :screen_one, :styles => { :medium => "800x600>", :thumb => "110x80#" },
:storage => :s3,
:s3_credentials => {
:access_key_id => ENV['accesskeyishere'],
:bucket => ENV['sitebuilderreport'],
:secret_access_key => ENV['secretaccesskeyishere']
}
I've changed the access keys since this is a public post :)
I met the same problem (missing :bucket every single where). The answer below works perfectly in my case.
a. Add these to .bash_profile (Note: Fill in with your Amazon account credentials)
export AWS_ACCESS_KEY_ID=XXXXXXXXXX
export AWS_SECRET_ACCESS_KEY=XXXXXXXXXX
export AWS_BUCKET=XXXXXXXXXX
b. This is my development.rb (Note: Copy and paste without changing anything)
Paperclip.options[:command_path] = "/usr/local/bin/"
config.paperclip_defaults = {
:storage => :s3,
:s3_credentials => {
:bucket => ENV['AWS_BUCKET'],
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
}
}
Be sure you rebundle your Rails app with the latest paperclip and aws-s3 gems. Also, make sure you quit your Terminal and run everything again since this is an update to your .bash_profile file.
I hope everything works out now.
You should define the ENV[] variables in your user .bash_profile in mac os.
You should do "heroku config" to see your heroku environement keys for S3 and define it in your local environement.
For example:
$ heroku config
AWS_ACCESS_KEY_ID: your_S3_XXX_key<br />
AWS_SECRET_ACCESS_KEY: your_secret_XXX_key<br />
AWS_BUCKET: your_production_bucket<br />
DATABASE_URL: postgres://xxxxxxx<br />
[...]<br />
You should copy the access_key and secret in your .bash_profile file:
export AWS_ACCESS_KEY_ID=your_S3_XXX_key<br />
export AWS_SECRET_ACCESS_KEY=your_secret_XXX_key
export AWS_BUCKET=your_development_bucket => "Specify new bucket for your dev environement".
In case anyone is doing the same silly thing I did - and making a local script to source that exports all of the AWS environment variables - be sure you source it in the same Terminal session that you're generating the rails server in! If you use split windows (CMD SHIFT D), bear in mind that sourcing the proper environment variables in one does not do so in the other. Very silly mistake but I'm sure (or at least mildly hopeful) that I won't be the only one who makes it.
You can also simply use (filling in the correct values of course):
config.paperclip_defaults = {
:storage => :s3,
:s3_credentials => {
:bucket => 'AWS_BUCKET',
:access_key_id => 'AWS_ACCESS_KEY_ID',
:secret_access_key => 'AWS_SECRET_ACCESS_KEY'
}
}
I had the same problem and I had config/application.yml (not sure if its a legacy thing or where it came from) but this allows environment variables to be set within rails 'codebase'. I forgot it was here, ignored in heroku and was overriding some settings that were not set.doh!

aws-s3 error: AWS::S3::MissingAccessKey error, but keys have been defined?

I'm pretty new to ROR. I've recently deployed an app on heroku and have tried to add an attachment function to the app via paperclip.
I've followed all the steps in adding aws-s3 to my app. Here was my initial code:
user.rb (model)
has_attached_file :avatar,
:styles => {:small => "70x70>"},
:storage => :s3,
:s3_credentials => "#{RAILS_ROOT}/config/s3.yml",
:path => ":attachment/:id/:style/:basename.:extension"
validates_attachment_size :avatar, :less_than => 1.megabytes
validates_attachment_content_type :avatar, :content_type => ['image/jpeg', 'image/png']
s3.yml (file is located in config folder) note: all of these buckets exist on my aws-s3
development:
bucket: my_avatar-dev
access_key_id: amazonaccesskey
secret_access_key: amazon_secret_access_key
test:
bucket: myapp_avatar-test
access_key_id: amazonaccesskey
secret_access_key: amazon_secret_access_key
production:
bucket: myapp_avatar-pro
access_key_id: amazonaccesskey
secret_access_key: amazon_secret_access_key
gemfile
gem 'aws-s3'
When running this configuration, I would get a error page 500 error when loading my app. Running Heroku logs showed the following error: AWS::S3::MissingAccessKey (You did not provide both required access keys.
So I followed some advice and defined the key and secret_key as environment variables to heroku, using the following line of code:
heroku config:add S3_KEY=amazonaccesskey S3_SECRET=amazon_secret_key
I then added an initializer to test environments and launch via key or .yml file depending on environment, code is as follows:
initializers/s3.rb
if Rails.env == "production"
# set credentials from ENV hash
S3_CREDENTIALS = { :access_key_id => ENV['S3_KEY'], :secret_access_key => ENV['S3_SECRET'], :bucket => "myapp_avatar-pro"}
else
# get credentials from YML file
S3_CREDENTIALS = Rails.root.join("config/s3.yml")
end
user.rb model was then update to the following:
has_attached_file :avatar, :storage => :s3, :s3_credentials => S3_CREDENTIALS
I then deployed to heroku and tested the app, but I still keep getting the same error (page 500) and error code: AWS::S3::MissingAccessKey (You did not provide both required access keys.
How is this possible if I have defined the variables in heroku? Is there something I am missing? Is it possible it's something with the gem? Also, I'm using HAML for styling... not sure that matters at all, but just in case it does. I'm quite lost, so any help would be greatly appreciated. Thank you so much!
Having just worked through the same problem and trawling a number of similar posts. I found that any of the possible configurations in the above answer i.e. declaring all of the hashes in the model, using the .yml or using the initializer all work fine from my dev and on heroku as long as the S3 bucket is of US Standard type> The choice is just about how DRY you want to be.
When I originally set S3 up, I used a European bucket. This gave me the spurious error message:
AWS::S3::MissingAccessKey (You did not provide both required access keys.
I note from the AWS site : http://docs.amazonwebservices.com/general/latest/gr/index.html?rande.html
that AWS uses a specific endpoint address for each region to reduce latency and am guessing (because I am a novice coder) that the US standard is either a default or coded into the AWS-S3 plugin. (Maybe someone can edit this up into a more complete answer?)
I solved this problem with this:
:s3_credentials => {
:access_key_id => 'mykey',
:secret_access_key => 'mykey'

Resources