I know we have done a lot of work without really touching the application yet, but bear with me just a little longer. In this post, we are going to add image uploads to our application and configure AmazonS3.

In essence, we are going to allow users to upload a profile image and add a post image.

Let’s get started.

Amazon S3

First things first, sign into AmazonS3, or create an account here.

Note: You will likely need to add a credit card, but AmazonS3 image hosting is very affordable.

Now, create a new bucket, which can be anything you want. You can just use the default setup, but take note of your bucket region.

If you ever need to find your bucket region, simply click on your bucket name and your region will be displayed in the URL.


Finding your Amazon S3 Region

Learn more about AmazonS3

Secret Access Keys

To set up Amazon for image hosting, we are going to need to get a hold of our access keys. If you just set up an account with AmazonS3, these keys will be provided to you.

Note: Make sure you save them, as they won’t be available again!

Even though these keys are provided to you, I highly recommend you create an IAM user instead.

I’ve embedded a video below from Amazon on how to accomplish this task.

Setting up IAM Users

Adding S3 Credentials

Now that you have your new IAM security credentials, let’s add them to our .env file we created in the first post.

# Add your AmazonS3 keys:

Add The Carrierwave Gem

To learn more about Carrierwave, click here.

# in your gemfile add:
gem 'carrierwave', '~> 1.0' # or the latest version if old...
bundle install
rails g uploader Post
rails g uploader User
# Note, I am creating two uploaders here for posts and users. 
# However, you could just use one file if the attributes are exactly the same. 
# Now open app/uploaders/user_uploader.rb and uncomment:
include CarrierWave::MiniMagick 

# Also, add:

if Rails.env.production?
  storage :fog
  storage :file

# Note: Delete or modify any existing storage statements if applicable
# Now you can play around with creating different versions of your images like so:

  version :thumb do
     process resize_to_fit: [50, 50]

   version :small do
     process resize_to_fit: [150, 150]
     process :quality => 100

  version :thumb do
     process resize_to_fit: [200, 200]
     process :quality => 100

# You can also decide what files types you will allow: 

  def extension_whitelist
    %w(jpg jpeg gif png)

# Now repeat the same process in app/uploaders/post_uploader.rb
# Note: You can play around with different image sizes as post images will be larger.

# Next open app/models/user.rb and add:
   mount_uploader :img, UserUploader
# Repeat the same process for app/models/post.rb, with slight modifications
   mount_uploader :cover_image, PostUploader
# Remember we set up :img and :cover_image when we set up our post and user model.

Let’s now install the FOG AWS Gem

Learn more about the fog-aws gem here

# Open your gem file and add:
gem 'fog-aws'
bundle install

# Now we need to create an initializers file called carrierwave.rb
# Now inside that file add:
CarrierWave.configure do |config|
 config.fog_provider = 'fog/aws' 
 config.fog_credentials = {
      :provider => 'AWS'
      :aws_access_key_id => ENV["AWS_ACCESS_KEY_ID"],
      :aws_secret_access_key => ENV["AWS_SECRET_ACCESS_KEY"]
      :region => ENV["REGION"]

config.fog_directory = ENV[FOG_DIRECTORY]
config.fog_public     =  false 
config.fog_attributes = { cache_control: "public, max-age=#{365.days.to_i}" }


Let Heroku Know

We now need to tell Heroku about our AmazonS3 credentials.

# In the terminal run:
heroku config:set AWS_ACCESS_KEY_ID=your-key-id AWS_SECRET_ACCESS_KEY=your-secret-key REGION=your-region FOG_DIRECTORY=your-bucket_name
# Check that it worked by running 
heroku config

Let’s do a quick git commit

git add .
git commit -m Added Carrierwave and Fog-Aws for Amazon image uploads'
git push origin master
git push heroku master

Adding Support for Gravatars

let’s do one last thing before we move onto the next post. When a user logs in and edits their profile, I want them to be able to see a profile picture. To do this, we are going to show their Gravatar by default. We are also going to give users the opportunity to upload a custom profile image to replace their Gravatar if they want.

Learn more about Gravatars here.

Creating A Users Helper

# Go to app/helpers and create users_helper.rb
# add:
module UsersHelper

# Add a Gravatar for the profile page:
 def gravatar_for(user, size: 190)
 gravatar_id = Digest::MD5::hexdigest(user.email.downcase)
 gravatar_url = "https://secure.gravatar.com/avatar/#{gravatar_id}?s=#{size}"
 image_tag(gravatar_url, alt: user.first_name + '' + user.last_name, class: "gravatar")

# Notice, the alt tag for the image. 
# Add a second version for displaying Gravatars in the main menu. 

def header_gravatar_for(user, size: 30)
gravatar_id = Digest::MD5::hexdigest(user.email.downcase)
gravatar_url = "https://secure.gravatar.com/avatar/#{gravatar_id}?s=#{size}"
image_tag(gravatar_url, alt: user.first_name + '' + user.last_name, class: "rounded-circle header-profile-img")


# Note: We can now call it in our users view with:
<%= gravatar_for @user %> # Once this is set up!
# To display the header Gravatar in the main menu, we can do this:
<%= header_gravatar_for(current_user) %> # Once this is set up!
# Note: The current_user method is automatically given to us by Devise.

# We can also create different CSS calls for each Gravatar like so:
.gravatar {
    padding: 0.25rem;
    background-color: #fff;
    border: 1px solid #dee2e6;
    border-radius: 0.25rem;
    max-width: 100%;
    height: auto;

.header_gravatar {
    border-radius: 50% !important;

Including the Users Helper

For the Gravatars method to work, we need to include the Users Helper in our Application Controller

# Open app/controllers/application_controller.rb and add:
include UsersHelper

Let’s now do our final commit

git add .
git commit -m Added a Users Helper for displaying Gravatars
git push origin master
git push heroku master

In the next post, we will create a custom Devise controller, where users will be able to update their profile image, their password, and demographic information. Admins and VIP’s will also be able to create, view, and delete users.

We will also create an admin module and move our new user's controller into it.

See you at the next post.

Click here to view part 5. Or click here to go back to part 3.