If you want your Ruby on Rails application to handle files, such as images, videos, PDFs and etc, you are in the right place.
First, let's understand:
What's Active Storage?
Active Storage is a tool that facilitates file uploads to cloud storage services, such as Amazon S3 (which we will use in this project), Google Cloud Storage, or Microsoft Azure, and attaches these files to Active Record objects. It also comes with a local disk-based service for development and testing and supports file mirroring to subordinate services for backups and migrations.
Before installing Active Storage in your application, it is necessary to install some third-party software for file analysis and processing support. Here is the list of necessary software:
- libvips v8.6+ or ImageMagick: for image analysis and transformation.
- ffmpeg v3.4+: for video previews and ffprobe for video/audio analysis.
- poppler or MuPDF: for PDF previews.
- Additionally, it is necessary to add the image_processing gem if your application will use image files.
I'll walk you through installing Active Storage by building an application together.
So, let's create the application!
Step 1: Create Your Rails Project
rails new name_project
Step 2: Configure AWS SDK in Your Project
- Add the following to your Gemfile:
# Gemfile
gem 'aws-sdk-s3'
- Then, in your terminal, run:
bundle install
This will install all the necessary packages, including the new one we just added.
Step 3: Add Active Storage to the Project
Run the following commands to install Active Storage and create the necessary tables:
rails active_storage:install
rails db:migrate
This will generate a migration to create the active_storage_blobs and active_storage_attachments tables.
Verification:
After running these commands, verify that the tables were created correctly in the database. You can do this by accessing the Rails console and inspecting the tables:
- Open the Rails console:
rails console
- Check that the required Active Storage tables were created:
ActiveRecord::Base.connection.tables
- You should see the following tables listed: active_storage_blobs active_storage_attachments active_storage_variant_records
Step 4: Create the S3 Bucket
Follow this article : How to create a bucket in AWS S3?
Step 5: Configure Secure Credentials
You can do this using environment variables or your credentials file. In this example, we'll use a .env file.
#.env
AWS_ACCESS_KEY_ID="your-key-id"
AWS_SECRET_ACCESS_KEY="your-secret-access-key"
AWS_REGION="bucket-region"
S3_BUCKET_DEVELOPMENT="bucket-name"
Make sure to replace the placeholders with your actual values.
Step 6: Configure File Uploads in Rails
Add the following configuration to your config/storage.yml:
# config/storage.yml
amazon:
service: S3
access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %>
secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %>
region: <%= ENV['AWS_REGION'] %>
bucket: <%= ENV['S3_BUCKET_DEVELOPMENT'] %>
Note: You can create different names for each bucket configuration. In this example, we are using "amazon", but you might use names like "amazon_development" or "amazon_production" to make it more readable and easier to manage multiple environments. This approach helps you distinguish between configurations for different environments.
Step 7: Update the Storage Service in the Environments
Update the storage service for the necessary environments. In this case, we'll do it for the development environment.
# config/environments/development.rb
config.active_storage.service = :amazon
Note: It's important to configure the storage service for each environment (development, test, and production) to ensure that your application works correctly in all scenarios.
Step 8: Implement File Uploads in a Model
As an example, let's create a Post model that includes text content and an attached image. In this illustration, we will allow a single image file to be attached to a post.
First, note that you don't need to include a column for the image in the Post model's database migration. Active Storage will handle the storage of the image data in separate tables.
Add the following to your model to enable file uploads:
# app/models/post.rb
class Post < ApplicationRecord
has_one_attached :image
end
Other Possible Attachments:
Single File Attachments: You can attach a single file to a record using has_one_attached as shown in the example. This is useful for models that require only one file attachment, such as a profile picture or a single document.
Multiple File Attachments: If you need to attach multiple files to a single record, you can use has_many_attached. This is useful for models that need to handle multiple files, such as an album with multiple photos, documents or a post with multiple attachments.
Step 9: Accept Attribute :image in Controller
To handle file uploads, you need to permit the :image attribute in the controller. This allows the form to submit the file to your model.
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
# other actions (index, etc.)
def create
@post = Post.new(post_params)
if @post.save
redirect_to @post, notice: 'Post was successfully created.'
else
render :new
end
end
private
def post_params
params.require(:post).permit(:content, :image)
end
end
This ensures that the :image attribute is accepted when creating or updating a post.
Step 10: Create a Form to Handle File Uploads
Add a file field to your form for uploads:
<!-- app/views/posts/new.html.erb -->
<%= form_with(model: post, local: true) do |form| %>
<!-- another fields in the form -->
<div class="field">
<%= form.label :image %>
<%= form.file_field :image %>
</div>
<%= form.submit %>
<% end %>
Step 11: Display the Uploaded File in the Post
Modify your view to display the uploaded file:
<!-- app/views/posts/index.html.erb -->
<p>
<strong>Image:</strong>
<%= image_tag post.image if post.image.attached? %>
</p>
Improving:
Add a link to download the image and specify the size:
<!-- app/views/posts/index.html.erb -->
<p>
<strong>Image:</strong>
<% if post.image.attached? %>
<%= link_to image_tag(post.image, size: "200x200", alt: "image file"), rails_blob_path(post.image, disposition: "attachment") %>
<% end %>
</p>
Step 12: Test the Upload
To ensure that file uploads are working correctly, follow these steps for verification:
Check Database Records:
- Open the Rails console:
rails console
- Verify that the active_storage_blobs and active_storage_attachments tables contain the expected records:
ActiveStorage::Blob.last
ActiveStorage::Attachment.last
Check on AWS Bucket:
Code repository: Upload_file_s3
References:
For more information on Active Storage, please access to the official Active Storage Overview web site.