Yi-Ning's Note

Upload file to S3 using Active Storage

July 30, 2018 | 3 Minute Read

Goal: create an image model and upload images to Amazon S3 using Active Storage with Rails 5.2.

  • Run rails new image-lib to create a rails project
  • Run rails active_storage:install
  • Run rails g model Image description:string to create image model
  • Run rails db:migrate to create tables for image model and active storage
  • Update Image model to have a file at /app/models/image.rb:
class Image < ApplicationRecord
  has_one_attached :file
end

 

  • Run rails g controller image new index create to create Image controller with new, index and create actions
  • Update new view with a form at /app/views/image/new.html.erb
<%= form_for :image, :url => {action: "create"} do |f| %>
  <p>description: <%= f.text_field :description %></p>
  <p>file: <%= f.file_field :file %></p>
  <%= f.submit "Create" %>
<% end %>
  • Update new and create controller at /app/controllers/image_controller.rb
  def new
    @image = Image.new
  end

  def create
    data = params.require(:image).permit(:description, :file)
    @image = Image.new(data)
    respond_to do |format|
      if @image.save
        format.html { redirect_to image_index_path }
      end
    end
  end
  • Update new view at /app/views/image/index.html.erb to display list of images and its description
<h1>Image#index</h1>
 <% @images.each do |t| %>
 <p><%=t.name %></p>
  <% if t.file.attached? %>
    <%= image_tag(url_for(t.file)) %>
  <% end %>
<% end %>
  • Update index controller at /app/controllers/image_controller.rb
<h1>Image#index</h1>
 <% @images.each do |t| %>
 <p><%=t.description %></p>
  <% if t.file.attached? %>
    <%= image_tag(url_for(t.file)) %>
  <% end %>
<% end %>

 

Check point: you should be able to upload a file at /image/new and see the image at /image/index. Now you’re able to save the file locally, next step is to upload these images to Amazon S3

 

Configure storage target to Amazon S3

  • Go to config/storage.yml and comment out amazon section
  • Update region and bucket name. You can find these information in our Amazon S3 account:
# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
amazon:
  service: S3
  access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
  secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
  region: **us-east-2**
  bucket: **yh-upload-to-s3**
  • Add Amazon s3 SDK in your Gemfile, install the gem
gem "aws-sdk-s3", require: false
  • Create AWS IAM user that has permissions: s3:ListBucket, s3:PutObject, s3:GetObject, and s3:DeleteObject
  • Run EDITOR=VIM rails credentials:edit to decrypted credentials.yml.enc  and update access key id and secret access key
  • uncomment AWS section, and enter proper access_key_id and secret_access_key for the AWS IAM user
aws:
 access_key_id: {your-access-key}
 secret_access_key: {your-secret-access-key}
  • Change your development storage service to use S3 at /config/environments/development.rb
config.active_storage.service = :amazon

Check point: you should be able to upload a file at /image/new, and these files should upload to your AWS S3 bucket

Useful links: