Integrate AWS S3 with ActiveStorage in Rails

This article will discuss how to integrate AWS S3 in a Ruby on Rails application using ActiveStorage.

Start by creating an application, installing active storage, generating a scaffold and migrating.

1
2
3
4
rails new aws-s3-tutorial
rails active_storage:install
rails generate scaffold User name
rails db:migrate

Use the dot-env gem for storing API keys in the .env file. Install dot-env by adding it to Gemfile:

1
2
gem "dotenv-rails"
gem "aws-sdk-s3", require: false

Now run the command bundle install.

Next, create a free AWS account and get the API keys. To get the secret keys, first click on S3.

Screen Shot 2020-06-28 at 8.50.30 PM.png

Now create a bucket.

Screen Shot 2020-06-28 at 8.51.22 PM.png

Next, add a user to the newly created bucket.

Screen Shot 2020-06-28 at 8.57.25 PM.png

After creating a user, grant them access to S3.

Screen Shot 2020-06-28 at 8.59.10 PM.png

Here you will find the keys.

Screen Shot 2020-06-28 at 9.04.43 PM.png

Add two files, .env and .env.sample, in the project root and add .env in the .gitignore because we don’t want the secret keys to be visible in git or anywhere else.

Add this to your .env file:

1
2
3
AWS_ACCESS_KEY_ID=youraccesskeyid
AWS_SECRET_ACCESS_KEY=yoursecretaccesskey
AWS_BUCKET=yourbucket

Of course, you need to replace these dummy keys with your original ones. Also, add dummy values to .env.sample so as to send this file to git.

1
2
3
AWS_ACCESS_KEY_ID=dummyaccesskeyid
AWS_SECRET_ACCESS_KEY=dummysecretaccesskey
AWS_BUCKET=dummybucket

Configure the config/storage.yml file with the following line:

1
2
3
4
5
6
7
  amazon:
    service: S3
    access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %>
    secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %>
    region: “your selected region here”
    bucket: <%= ENV['AWS_BUCKET'] %>

Tell ActiveStorage which service to use for image uploads by putting this line in the production.rb file:

1
config.active_storage.service = :amazon

Make sure you have this line in your application.js file:

1
require("@rails/activestorage").start()

Now that the basic setup of S3 is done, let’s move on to the implementation.

In app/models/user.rb:

1
2
3
4
5
# app/models/user.rb

class User < ApplicationRecord
 has_one_attached :avatar
end

Add this to the _form.html.haml partial:

1
2
3
4
5
<div class="field">
 <%= form.label :avatar %>
 <%= form.file_field :avatar %>
</div>

The view that displays the image (such as show.html.haml) needs to include the following code:

1
2
3
<div>
 <%= image_tag @user.avatar if @user.avatar.present? %>
</div>

In your app/controllers/users_controller, permit avatar.

1
2
3
def user_params
 params.require(:user).permit(:name, :avatar)
end

Before running and testing, export the environment variables:

1
2
3
export AWS_ACCESS_KEY_ID=youraccesskeyid
export AWS_SECRET_ACCESS_KEY=yoursecretaccesskey
export AWS_BUCKET=yourbucket

S3 is now installed and configured. Happy uploading!