How to set up AWS s3 bucket on Rails with ActiveStorage
In this blog post, I’ll walk through the entire setup of the AWS s3 bucket for Ruby on Rails with ActiveStorage.
Let’s begin with ActiveStorage configuration first and I would assume you already have rails project generated where you want to implement this functionality :
First, we going to install ActiveStorage by running this command in your terminal$ rails active_storage:install
, it will generate some migration files for you so went we need to run it as well $ rails db:migrate
.
These tables will be added to your schema, the last step we would need to set up ActiveStorage associations, which works just like ActiveRecord associations from a model point of view.
In the Info class, I created 4 ActiveStorage associations, 2 with has_one_attached which would store only one instance of a media and would be equivalent of has_one in ActiveRecord, and 2 with has_many_attached that would store many media associations and works just like has_many in ActiveRecord.
Now let’s set up an AWS s3 bucket. Log in into your AWS account, click on services and choose s3:
then we’re going to click on create new bucket button:
name your bucket, choose the region and uncheck “Block all public access” then hit create bucket button.
Now you have a bucket created, we just need two more things to configure in order for it to work: CORS and policy. Let’s open the bucket and navigate to the Permissions section and add the following to Policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::YOUR_BUCKET_NAME"
},
{
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::YOUR_BUCKET_NAME/*"
}
]
}
and following to the CORS block:
[
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"GET",
"PUT",
"POST",
"DELETE"
],
"AllowedOrigins": [
"*"
],
"ExposeHeaders": []
},
{
"AllowedHeaders": [],
"AllowedMethods": [
"GET"
],
"AllowedOrigins": [
"*"
],
"ExposeHeaders": []
}
]
Alright, now we have your bucket configured, now let’s add bucket keys to the .env (don’t forget to add them to the platform you’re deploying it to as well)
and let’s go to config/storage.yml and make sure you have uncommented s3 configuration that by default is I believe would be commented out.
Also, make sure that you’re pointing at the same server in region settings.
Now in config/initializers, we need to declare what type of storage we are going to use, for production we should change it to amazon, for the development I will leave it up to you, you can use local or you can switch it on to amazon as well so you can test it out before deployment.
in config/initializers/production.rb change config.active_storage.service from local to :amazon.
config.active_storage.service = :amazon
here is an example of my production file:
So Lots of work we’ve done and came a long way. Now we have everything set up and ready to upload pictures to s3.
To accept files, in ERB we can use the following:
for many files to be loaded at ones (for has_many_attached)
and the example above for a single file upload.
Now let’s move to the controller to do some ActiveStorage manipulations.
Since I have only one instance of the Info class and I allow updates from many different places on my website I’ve set it up like that, the point being that you can use .attach to and pass the image params to create those associations and ActiveStorage would do all of the magic for you behind the scenes.
To display images and make a link to delete them I’ve set it up like that:
P.S.
If you still have problems with ActiveStorage You can try to use this setup for config/storage.yml instead:
I hope it was helpful, do not hesitate to reach out and ask any questions you may have. You can reach out to me here and thank you for reading.