Rails 5.2 added a built-in solution for handling file uploads using Active Storage.
Let’s say, we have an Candidate
model that has two attachments resume
and
cover_letter
.
class Candidate < ApplicationRecord
has_one_attached :resume
has_one_attached :cover_letter
end
# Attach cover_letter to the candidate.
candidate = Candidate.last
candidate.cover_letter.attach(
io: File.open("path/to/cover_letter"),
filename: "cover_letter.txt",
content_type: "text/plain"
)
Before Rails 6.1, only one cloud storage service (Amazon S3, Google cloud storage, Microsoft Azure storage) could be used for overall application.
But, there could be cases where our application might require to upload images to different storage services.
In Rails 6.1
For the above example, let’s say we want to upload resume
to Amazon S3
and cover_letter
to Google cloud
.
We need to pass service
parameter to has_one_attached
method as shown
below:
class Candidate < ApplicationRecord
has_one_attached :resume, service: :amazon
has_one_attached :cover_letter, service: :google
end
In the above example, resume
of the candidate is stored to amazon
and cover_letter
to google
.
storage.yml
can be configured as below for multiple storage services:
test:
service: Disk
root: <%= Rails.root.join("tmp/storage") %>
local:
service: Disk
root: <%= Rails.root.join("storage") %>
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: <%= Rails.application.credentials.dig(:aws, :aws_region) %>
bucket: <bucket_name>
google:
service: google_cloud
project: <project_name>
credentials: <%= Rails.root.join("path/to/gcs.keyfile") %>
bucket: <bucket_name>
NOTE:
-
If the
service
is not specified the defaultservice
set inconfig/environments
is used for storage. -
If specified service is not properly configured,
has_one_attached
would throw an error. -
If our project is already using Active Storage and when we upgrade to Rails 6.1, we should run
rake app:update
to make sureservice_name
column is added to the internalActiveStorageBlob
model.