Skip to content

Instantly share code, notes, and snippets.

@marcusmalmberg
Last active June 14, 2021 23:22
Show Gist options
  • Star 26 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save marcusmalmberg/4073144 to your computer and use it in GitHub Desktop.
Save marcusmalmberg/4073144 to your computer and use it in GitHub Desktop.
Guide to setup CarrierWave which will upload a file to Amazon S3 in production environment and use local storage in development and test

CarrierWave home

https://github.com/jnicklas/carrierwave

This example will create an uploader that will upload a file stored in a model Model. The file will be stored locally in development and test environment and will use Amazon S3 in production.

CarrierWave installation

First add the gems.

# Gemfile
gem 'carrierwave'
gem 'fog'

Install gems.

bundle install

CarrierWave create uploader

Generate uploader

rails generate uploader Model

Create model Model

rails generate model model file:string
rake db:migrate

Update the ModelUploader

# app/uploaders/model_uploader.rb 
class ModelUploader < CarrierWave::Uploader::Base

  # 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

Configure the model Model

# app/models/model.rb 
class Model < ActiveRecord::Base
  mount_uploader :file, ModelUploader
  attr_accessible :file
end

Configure FOG storage

Configure carrierwave to use Amazon S3. The AWS credentials that's needed in the config can be found here: https://portal.aws.amazon.com/gp/aws/securityCredentials#access_credentials and visit https://console.aws.amazon.com/s3/home# to setup a bucket.

# config/initializers/carrierwave.rb
# This file is not created by default so you might have to create it yourself.

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      => '<your key goes here>',            # required
    :aws_secret_access_key  => '<your secret key goes here>',     # required
    :region                 => 'eu-west-1'                        # optional, defaults to 'us-east-1'
  }
  config.fog_directory  = '<bucket name goes here>'               # 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

Image quality

# config/initializers/carrierwave.rb
module CarrierWave
  module MiniMagick
    def quality(percentage)
      manipulate! do |img|
        img.quality(percentage.to_s)
        img = yield(img) if block_given?
        img
      end
    end
  end
end

Convert image to PNG

# app/uploaders/my_uploader.rb
process :convert => 'png'
def filename
    super.chomp(File.extname(super)) + '.png' if original_filename
end

Conditional processing / versions

# app/uploaders/my_uploader.rb
version :avatar, if: :create_avatar? do
    process :resize_to_limit => [200, 200]
end

def create_avatar?(img = nil)
    # conditions, return true / false
    # e.g. model.should_create_avatar?
end
@hiro2016
Copy link

hiro2016 commented Dec 8, 2017

Thanks for a very useful guide.
I faced some issue deploying my app on ec2, however:
NameError: uninitialized constant CarrierWave::Storage::Fog.
Moving the section below to the last solved it.

  if Rails.env.production?
    CarrierWave.configure do |config|
      config.storage = :fog
    end
  end

@fagianijunior
Copy link

How to make a link to download this file? in my case a pdf or jpg files

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment