Carrierwave fails in production: Can't convert nil into string - ruby-on-rails

I'm using Fog and uploading to S3. Uploading works fine in development, but when in production, it gives me this error:
TypeError (can't convert nil into String):
app/controllers/pictures_controller.rb:29:in `create'
(that line is where the picture gets saved). That's the end of the stack trace.
When I go into the console and do:
p = Picture.new(image: "~/rails_apps/my_app/current/app/assets/images/rails.png")
It gives me the following in production:
CarrierWave::FormNotMultipart: CarrierWave::FormNotMultipart
...but makes no protest in development. Perhaps that is a clue.
Any ideas why uploads aren't working in production?
Here's my carrierwave.rb initializer:
CarrierWave.configure do |config|
config.fog_credentials = {
:provider => 'AWS', # required
:aws_access_key_id => ENV['AWS_ACCESS_KEY_ID'], # required
:aws_secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']#, # required
}
if Rails.env.production?
config.fog_directory = 'mydir' # required
else
config.fog_directory = 'mydir-development' # required
end
config.fog_public = true # optional, defaults to true
config.fog_attributes = {'Cache-Control'=>'max-age=315576000'} # optional, defaults to {}
end

I encountered similar problem, it turned out that my carrierwave and fog gem are outdated(they worked perfectly until I upgraded to Rails 4). Maybe you can give it a try.
gem 'carrierwave', '0.9.0'
gem 'fog', '~> 1.3.1'

Related

Fog/Carrierwave config for Rails app on AWS Elastic Beanstalk

I'm trying to set up Carrierwave and Fog to handle image and file uploads on a rails app that I have hosted on AWS' Elastic Beanstalk.
I'm a little confused on how to properly set up the Fog config.
I tried using my AWS Access and Secret keys (commented out in the example below). That through an error on my EB CLI (ERROR: NotAuthorizedError - Operation Denied. The security token included in the request is invalid.)
I'm tyring to use IAM instead of having my Access/Secret codes in my ruby code. Can anyone tell me how to set this up properly?
Here's my config file:
CarrierWave.configure do |config|
# Use local storage if in development or test
if Rails.env.development? || Rails.env.test?
CarrierWave.configure do |config|
config.storage = :file
end
end
# Use AWS storage if in production
if Rails.env.production?
CarrierWave.configure do |config|
config.storage = :fog
end
end
config.fog_credentials = {
:provider => 'AWS', # required
# :aws_access_key_id => 'My Access', # required
# :aws_secret_access_key => 'My Secret', # required
:use_iam_profile => true,
:region => 'eu-west-2' # optional, defaults to 'us-east-1'
}
config.fog_directory = 'elasticbeanstalk-us-west-2-XXXXXXXXXX' # required
#config.fog_host = 'https://assets.example.com' # optional, defaults to nil
config.fog_public = false # optional, defaults to true
config.fog_attributes = {'Cache-Control'=>'max-age=315576000'} # optional, defaults to {}
end
This is a setup that works for me:
config/initializers/carrierwave.rb
CarrierWave.configure do |config|
config.fog_provider = 'fog/aws' # required
config.fog_credentials = {
provider: 'AWS', # required
aws_access_key_id: ENV['aws_access_key_id'], # required
aws_secret_access_key: ENV['aws_secret_access_key'], # required
#region: 'Singapore', # optional, defaults to 'us-east-1'
#host: 's3.example.com', # optional, defaults to nil
#endpoint: 'olucube-images.s3-website-ap-southeast-1.amazonaws.com', # optional, defaults to nil
}
config.fog_directory = ENV['fog_directory'] # required
#config.fog_public = false # optional, defaults to true
# config.fog_attributes = { 'Cache-Control' => "max-age=#{365.day.to_i}" }, # optional, defaults to {}
end
and I used figaro gem to hold my credentials as follow:
config/application.yml
aws_access_key_id: 'XXXXXXXXXXXXXXXXXXXX'
aws_secret_access_key: 'XXXXXXXXXXXXXXXXXX'
fog_directory: 'myAppName'
This was a bit a of a wild ride. I had a hard time figuring out that Figaro gem. It's probably simple but I didn't really understand it. So for a test, I put my keys directly in the code. It still didn't work.
I pushed my code to github (publicly) and didn't think too much of it. I was going to change the keys just in case. Before I was able to do that someone found my code on github and gained access to my AWS account. They started a bunch of EC2 instances and racked up $3000 worth of usage in a few hours!
My AWS account got suspended and I'm still dealing with having the charges reversed.
Anyway. I found out that you can actually set environment variables on the Elastic Beanstalk web interface. Its under Configuration → Software Configuration. So I did that instead of using Fiagro (much safer IMO). Now it works great. I simplified my Carrierwave config file to only use AWS calling the environment variables from EB. Here's the file:
# config/initializers/carrierwave.rb
CarrierWave.configure do |config|
config.fog_provider = 'fog/aws'
config.fog_credentials = {
provider: 'AWS',
aws_access_key_id: ENV['S3_KEY'],
aws_secret_access_key: ENV['S3_SECRET'],
region: ENV['S3_REGION']
}
config.fog_directory = ENV['S3_BUCKET']
config.fog_public = false
config.storage = :fog
end
I changed my uploader files to use fog too. Here's an example:
# app/uploaders/image_uploader.rb
class ImageUploader < CarrierWave::Uploader::Base
storage :fog
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
def extension_white_list
%w(jpg jpeg gif png)
end
end
Everything works great now. I hope this helps someone else.

Carrierwave and S3 not working

I have a problem with authentication, i try to upload but i get this
The request signature we calculated does not match the signature you provided. Check your key and signing method.
initializer carrierwave.rb
CarrierWave.configure do |config| # optional, defaults to "fog"
config.fog_credentials = {
provider: 'AWS', # required
aws_access_key_id: ENV["AWS_ACCESS_KEY_ID"], # required
aws_secret_access_key: ENV["AWS_ACCESS_SECRET_KEY"], # required
}
config.fog_directory = ENV["AWS_BUCKET_NAME"] # required
config.fog_attributes = { 'Cache-Control' => "max-age=#{365.day.to_i}" } # optional, defaults to {}
end
gem "carrierwave"
gem "fog"
gem "figaro"
set the environment variables
i also created a bucket in S3.
Is there anything i am missing here? It works locally though.
Also changed the image_uploader.rb to storage :fog

ckeditor Rails 4 carrierwave s3 fog

I am having a lot of difficulties uploading images to S3 via CarrierWave & Fog. I already had set up carrierwave and s3 and had no problems but then I added Ckeditor. The biggest problem I am having is that all the images I upload using the Ckeditor photouploader have an expiration time. I don't want them to expire and I can't find any documentation on how to change this.
CarrierWave.configure do |config|
config.root = Rails.root.join('tmp') # adding these...
config.cache_dir = 'carrierwave' # ...two lines
config.fog_credentials = {
:provider => 'AWS', # required
:aws_access_key_id => ENV['AWS_KEY'], # required
:aws_secret_access_key => ENV['AWS_SECRET'], # required
:region => ENV['AWS_REGION'], # optional, defaults to 'us-east-1'
}
config.fog_directory = ENV['FOG_DIR'] # required
config.fog_public = false # optional, defaults to true
config.fog_attributes = {'Cache-Control'=>"max-age=#{365.day.to_i}"} # optional, defaults to {}
end
So I have solved the fact that config.fog_public needs to be set to true on s3 to receive urls without expiration dates. Does anyone know how to change a lot of images that are on s3 with expiration dates to public without having to reupload all of the images?

carrierwave not recognizing keys

I just pulled an older version of a project I'm working on in rails from github and am having problems with carrierwave for image upload. I used the figaro gem to store my secret keys so they were not in the file I pulled down (figaro puts an application.yml file that then gets listed in .gitignor). So I added the figaro configuration, but carrierwave still refuses to work. I even tried putting the keys into the carrierwave configuration directly to see if it was something with figaro, but no luck.
My config/initializers/carrierwave.rb
CarrierWave.configure do |config|
config.fog_credentials = {
:provider => 'AWS',
:aws_access_key_id => ENV['AWS_KEY_ID'],
:aws_secret_access_key => ENV['AWS_SECRET_KEY'],
:region => 'us-east-1',
}
config.fog_directory = 'bucketname'
config.fog_public = true
config.fog_attributes = {'Cache-Control'=>'max-age=315576000'}
end
I am pretty sure that my keys are being stored properly in my development environment, but I have no idea why carrierwave is not working like it did before.
Thanks!

Rspec and Carrierwave. When changing config.storage to file for testing, I get an ArgumentError is not a recognized storage provider exception

I have two carrierwave uploaders in my application. ImageUploader is for uploading locally and ImageRemoteUploader for uploading to Amazon S3 storage using fog. ImageUploader has storage set to :file and ImageRemoteUploader has storage set to :fog. This setup works fine, but when I start to set up my rspec tests, things change.
The problem arises when I change the ImageRemoteUploader to use :file storage during testing. I do this in my fog initialization file. The file,
/config/initializers/fog.rb, looks like:
CarrierWave.configure do |config|
if Rails.env.test?
config.storage = :file
config.enable_processing = false
else
config.fog_credentials = {
:provider => 'AWS', # required
:aws_access_key_id => 'XXXXXXXX', # required
:aws_secret_access_key => 'XXXXXX', # required
:region => 'XXXX' # optional, defaults to 'us-east-1'
}
config.fog_directory = 'xxx' # required
config.fog_public = true
end
end
When I do this, I get an ArgumentError is not a recognized storage provider carrierwave exception. When I use the fog credentials (I don't set config.storage to :file), the test works as expected.
Carrierwave 0.7.1, Rails 3.2.8, Ruby 1.9.3, Rspec 2.10
Thanks.
I'd try moving the config.storage and config.enable_processing lines into lib/initializers/carrierwave.rb, as recommended in the Carrierwave docs.
Fog also has its own mocking support, which is enabled by running Fog.mock! before the examples. This might be a better approach.

Resources