Public URL with Fog and Amazon S3 - ruby-on-rails

Versions of all RubyGems. I am using Ruby on Rails 3.1.3, Ruby 1.9.2, CarrierWave 0.5.8, and Fog 1.1.2.
I am using the CarrierWave RubyGem too for image uploading and the Fog RubyGem for Amazon S3 file upload.
In my CarrierWave initializer file I have:
CarrierWave.configure do |config|
config.fog_credentials = {
provider: 'AWS',
aws_access_key_id: 'xxx',
aws_secret_access_key: 'xxx'
}
if Rails.env.production?
config.fog_directory = 'bucket1'
elsif Rails.env.development?
config.fog_directory = 'bucket2'
else
config.fog_directory = 'bucket3'
end
config.fog_public = false
config.fog_authenticated_url_expiration = 60
end
I have an uploader file:
class PageAttachmentUploader < CarrierWave::Uploader::Base
CarrierWave.configure do |config|
if Rails.env.development? || Rails.env.development? || Rails.env.production?
config.fog_public = true
end
end
storage :fog
end
I am having two uploader files. I want one to be set to private and one to public.
I am trying to overwrite CarrierWave configuarations when PageAttachmentUploader is invoked and set the URL to public. This works like charm in the local machine, but it does not work in staging, sandbox and production.
I changed config.fog_public = true in the CarrierWave intializer. Even that does not work in sandbox. How do I fix this problem?

No, you should not use CarrierWave.configure directly in your uploaders as it will change the default configuration for all uploaders and not only each uploader.
I don't know if that's the best solution but you can change the default fog configuration directly by setting class methods in your uploaders like this :
class ImageUploader < CarrierWave::Uploader::Base
storage :fog
def self.fog_public
true # or false
end
end

Actually, the best way (I've found) is to do the following:
class ImageUploader < CarrierWave::Uploader::Base
storage :fog
configure do |c|
c.fog_public = true # or false
end
end
It feels more in line with CarrierWave's style to do it this way.

Related

Can carrierwave direct upload to local storage?

Sometimes I am away from internet and still need to work on upload pages. Carrierwave Direct seems to force storage :fog; with no way of overriding in dev.
Is it possible to tell Carrierwave Direct to use local storage (:file) and simply fallback to Carrierwave's development config settings?
Setting storage :file in carrierwave initializer under development config settings doesnt work...carrierwave_direct errors with "is not a recognized provider" from "<%= direct_upload_form_for #uploader do |f| %>".
I have attempted to work around carrierwave direct, but between forcing :fog, expecting a redirect url and expecting the direct_upload_form_for form method...carrierwave_direct is pretty much in charge.
Using storage :file in development would be a welcome feature for the carrierwave_direct gem. Does anyone know how to cleanly do this?
I think it can be done as follows:
CarrierWave.configure do |config|
if Rails.env.development? || Rails.env.test?
config.storage = :file
config.asset_host = ENV["dev_url"]
else
config.fog_provider = 'fog/aws' # required
config.fog_credentials = {
provider: 'AWS', # required
aws_access_key_id: ENV["aws_id"], # required
aws_secret_access_key: ENV["aws_key"], # required
region: ENV["aws_zone"] # optional, defaults to 'us-east-1'
}
config.fog_directory = ENV["aws_bucket"] # required
config.max_file_size = 600.megabytes # defaults to 5.megabytes
config.use_action_status = true
config.fog_public = false # optional, defaults to true
config.fog_attributes = { cache_control: "public, max-age=#{365.day.to_i}" } # optional, defaults to {}
end
end
And in your Uploader add in:
class SomeUploader < CarrierWave::Uploader::Base
if Rails.env.development? || Rails.env.test?
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
end

Carrierwave / Fog / S3 "is not a recognized storage provider"

I have a Rails app that is using Carrierwave for file uploads. It has been working fine but I want to start using Amazon S3 for my image storage. I am getting this error:
ArgumentError ( is not a recognized storage provider):
app/controllers/salons_controller.rb:52:in `update'
I have made sure I have the latest gems for Carrierwave and Fog. This is in my Gemfile:
gem 'carrierwave'
gem 'aws-sdk'
gem 'fog'
fog.rb looks like:
CarrierWave.configure do |config|
config.fog_credentials = {
:provider => 'AWS',
:aws_access_key_id => 'MYACCESSKEY',
:aws_secret_access_key => 'MYSECRETKACCESSKEY',
:region => 'us-east-1'
}
config.fog_directory = 'andrunix'
config.fog_public = true
config.fog_attributes = {'Cache-Control'=>'max-age=315576000'}
end
The Uploader class looks like:
class SalonImageUploader < CarrierWave::Uploader::Base
include CarrierWave::RMagick
storage :fog
def store_dir
# "andrunix" is the bucket name on S3
"andrunix/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
If I change the storage back to 'file', it works fine. Setting storage to 'fog' generates this error.
OK, I'm an idiot. :)
At some point, I don't know where, I added a fog.rb file with my CarrierWave configuration to the lib/carrierwave/storage directory. I got desperate, paid for a Railscasts subscription so I could watch episode #383 (http://railscasts.com/episodes/383-uploading-to-amazon-s3?autoplay=true) and at 3:02 I found the error of my ways. The Carrierwave configuration needed to be placed in config/initializers/carrierwave.rb.
I don't know where I got this other location but once I moved the config to the proper location, everything is good.
I just ran into the same problem, and people must be aware that any typo in the config file : "config/initializers/carrierwave.rb", leads to that error.

Rails Engine not uploading to s3 with Carrierwave

I am creating a rails plugin with rails new plugin my_plugin --mountable
This was quite some work to figure out but it is supposed to upload files to S3 with carrierwave, but it says ok but nothing is uploaded
Carrierwave is used to generate an uploader with rails g uploader photo
the file looks like this
# my_engine/app/uploaders/my_engine/photo_uploader.rb
# encoding: utf-8
module my_engine
class PhotoUploader < CarrierWave::Uploader::Base
# Choose what kind of storage to use for this uploader:
storage :file
# storage :fog
# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
end
the model had an mount :photo, PhotoUploader
module PdfGeneratorEngine
class Assemble < ActiveRecord::Base
attr_accessible :color, :photo, :qr_code_url, :text
mount_uploader :photo, PhotoUploader
end
end
my CarrierWave config file is this
CarrierWave.configure do |config|
config.fog_credentials = {
:provider => 'AWS',
:aws_access_key_id => 'MY_ACCES_KEY',
:aws_secret_access_key => 'MY_SECRET_KEY',
:provider => 'AWS',
:region => 'eu-west-1'
}
config.fog_directory = 'my.bucket.com'
config.fog_host = 'https://s3-eu-west-1.amazonaws.com/my.bucket.com'
config.storage = :fog
config.s3_use_ssl = true
config.fog_public = true
end
So first of all it starts screaming at fog_host, it is okay if it is asset_host
Next it's problem lies within s3_use_ssl, while it is an merged issue on CarrierWave's github. But the host is already defined as https:// so I don't see why that line is necessary.
After that it says 'Okay it's done' and when I try to check (with a deamon) for the file, there's nothing there.
What did I miss? Or is there something of an issue with CarrierWave and Rails mountable engines?
In your photo_uploader.rb
comment storage:file and uncomment storage:fog
# storage :file
storage :fog
--
Look at your fog.rb, Its inconsistent with what is given here
carrierwave#using-amazon-s3
CarrierWave.configure do |config|
config.fog_credentials = {
:provider => 'AWS', # required
:aws_access_key_id => 'xxx', # required
:aws_secret_access_key => 'yyy', # required
:region => 'eu-west-1' # optional, defaults to 'us-east-1'
:hosts => 's3.example.com' # optional, defaults to nil
:endpoint => 'https://s3.example.com:8080' # optional, defaults to nil
}
config.fog_directory = 'name_of_directory' # required
config.fog_public = false # optional, defaults to true
config.fog_attributes = {'Cache-Control'=>'max-age=315576000'} # optional, defaults to {}
end
Okay So there is a bit of a problem with CarrierWave.
I have quickly setup RightAws and now it uploads to S3 and I can find it from my deamon.
in my uploader I added
#s3 = RightAws::S3Interface.new('MY KEY', 'MY SECRET KEY')
#s3.put('my.bucket.com', assemble.photo.identifier ,params[:assemble][:photo])
Thanks for your help Nishant, CarrierWave would be a lot slicker and nicer but it currently does not work. There has been an issue for this in their github regarding use in Rails engines.

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.

Configure Environment to Use Different Storage Paths on Amazon S3 with Carrierwave

I would like to have distinct folders in my S3 bucket to keep the production database clear from the development environment.
I am not sure how to do this, here is the skeleton I've come up with in the carrierwave initializer:
if Rails.env.test? or Rails.env.development?
CarrierWave.configure do |config|
//configure dev storage path
end
end
if Rails.production?
CarrierWave.configure do |config|
//configure prod storage path
end
end
Two options:
Option1: You don't care about organizing the files by model ID
In your carrierwave.rb initializer:
Rails.env.production? ? (primary_folder = "production") : (primary_folder = "test")
CarrierWave.configure do |config|
# stores in either "production/..." or "test/..." folders
config.store_dir = "#{primary_folder}/uploads/images"
end
Option 2: You DO care about organizing the files by model ID (i.e. user ID)
In your uploader file (i.e. image_uploader.rb within the uploaders directory):
class ImageUploader < CarrierWave::Uploader::Base
...
# Override the directory where uploaded files will be stored.
def store_dir
Rails.env.production? ? (primary_folder = "production") : (primary_folder = "test")
# stores in either "production/..." or "test/..." folders
"#{primary_folder}/uploads/images/#{model.id}"
end
...
end
Consider the following initializer:
#config/initializers/carrierwave.rb
CarrierWave.configure do |config|
config.enable_processing = true
# For testing, upload files to local `tmp` folder.
if Rails.env.test?
config.storage = :file
config.root = "#{Rails.root}/tmp/"
elsif Rails.env.development?
config.storage = :file
config.root = "#{Rails.root}/public/"
else #staging, production
config.fog_credentials = {
:provider => 'AWS',
:aws_access_key_id => ENV['S3_KEY'],
:aws_secret_access_key => ENV['S3_SECRET']
}
config.cache_dir = "#{Rails.root}/tmp/uploads" # To let CarrierWave work on heroku
config.fog_directory = ENV['S3_BUCKET']
config.fog_public = false
config.storage = :fog
end
end
In development, the uploads are sent to the local public directory.
In test mode, to the Rails tmp directory.
And finally, in "else" environment (which is usually a production or staging environment) we direct the files to S3 using Environmental Variables to determine which bucket and AWS credentials to use.
Use different Amazon s3 buckets for your different environments. In your various environment .rb files, set the environment specific asset_host. Then you can avoid detecting the Rails environment in your uploader.
For example, in production.rb:
config.action_controller.asset_host = "production_bucket_name.s3.amazonaws.com"
The asset_host in development.rb becomes:
config.action_controller.asset_host = "development_bucket_name.s3.amazonaws.com"
etc.
(Also consider using a CDN instead of hosting directly from S3).
Then your uploader becomes:
class ImageUploader < CarrierWave::Uploader::Base
...
# Override the directory where uploaded files will be stored.
def store_dir
"uploads/images/#{model.id}"
end
...
end
This is a better technique from the standpoint of replicating production in your various other environments.

Resources