Active Storage is a feature in Rails(applicable in versions >= 5.2) which facilitates uploading files to a cloud storage service like Amazon S3, Google Cloud Storage, or Microsoft Azure Storage and attaching those files to Active Record objects. It comes with a local disk-based service for development and testing and supports mirroring files to subordinate services for backups and migrations.
Active storage provides an easy and streight forward way to upload images without using additional gems like paperclip, carrierwave, shrine (which were in most use before rails 5.2).
How to Setup Active Storage:
1. Create a new rails app
Here I am creating a new rails application but please read the post carefully and you can apply the main feature in your existing application as well.
rails new active-storage-demo
cd active-storage-demo
bundle install
2. Create a model into which we will use ActiveStorage for uploading image
Here at this stage I am creating a model with name Post, but I am just taking this for an example, you can choose any name for your resource. You just need to do few things in your model class.
Run following command into your terminal:
rails g scaffold post title:string content:text
3. Adding Active storage to application
Since Active Storage also require active_storage_blobs and active_storage_attachments tables to store attachments so we also need to create these tables as well. You need to run following command for getting migration for both tables:
rails active_storage:install
4. Run Migration
Now Run following commands to get all tables into your schema:
rails db:migrate
5. Add attachments attributes into model
Now add following line into your post model:
has_one_attached :cover_image
6. Permitting cover_image as params
Open your app/controllers/posts_controller.rb
and replace following method
def post_params
params.require(:post).permit(:title, :content)
end
with following:
def post_params
params.require(:post).permit(:title, :content, :cover_image)
end
7. Add cover_image field to form
Now since active storage attachment attributes will not be added to the table of model class, we need to add this into form manually. Add following snippet into app/views/posts/_form.html.erb
, before submit button
<%= form.label :cover_image %>
<%= form.file_field :cover_image %>
that's it. So far we have done everything to upload image and store this inot database.
8. Display active storage attachment to view
open your app/views/posts/show.html.erb
and following line to top of the file:
<%= image_tag @post.cover_image %>
If you want to make a check that whether cover_image
exists or not than you can use following snippet instead of above line:
<% if @post.cover_image.attached? %>
<%= image_tag @post.cover_image %>
<% else %>
No Cover Image Uploaded
<% end %>
And you are done.
Visit http://localhost:3000/posts/new and create a new post by uploading a new cover image for this post. Save it and display this post. You will see cover_image with post details.
These steps will work fine for development
and test
environment. But what if you want to upload image in production environment? You can not use local file system there to keep your images. You must use one the cloud providers mentioned in the beginning of the blog. Here I am going to show you that how we can store our images Amazon S3 cloud storage. You need to do following things for this:
1. Set amazon as active storage bucket
Open your config/environments/production.rb
and replace following line:
config.active_storage.service = :local
with
config.active_storage.service = :amazon
2. Configure storage.yml
Open your config/storage.yml
and uncomment following lines::
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: <%= Rails.application.credentials.dig(:aws, :aws_bucket) %>
However you must edit your credentials before uncommenting these lines and set your AWS credentials there. Run following command to set the AWS secrets.
rails credentials:edit
If you are not familiar with rails credentials and you want to use any gems(dotenv or figaro) for managing your env variables you can simply do following configuration.
amazon:
service: S3
access_key_id: <%= ENV['AWS_ACCESS_KEY'] %>
secret_access_key: <%= ENV['AWS_SECRET_KEY'] %>
region: <%= ENV['AWS_REGION'] %>
bucket: <%= ENV['AWS_BUCKET'] %>
Just make sure to define these ENV vars in your production environment.
3. Add aws-sdk gem in your Gemfile:
Add following line to bottom of your Gemfile and Run bundle install:
gem "aws-sdk-s3", require: false
now run
bundle install
That's it.