When creating an application with Rails, image data is saved in the images folder of assets, but if you use AWS and Rails Active Storage, you can save the image data in the cloud. I'm thinking of deploying my application using AWS, so I've summarized how to use Active Storage to save to AWS S3.
There is software called ImageMagick that has a function to change the image size in Active Storage, so install it in advance.
python
$ brew install imagemagick
Edit the Gemfile and do a bundle install.
gemfile
gem 'mini_magick', '~> 4.8'
python
$ bundle install
First, install Active Storage and create the active_storage_blobs and active_atorage_attachment tables.
python
$ bin/rails active_storage:install
$ bin/rails db:migrate
Add a class method to the model where you want to save the image. The has_one_attached method is used when you want to save one file. Use the has_many_attached method when you want to save multiple files. Also, add model attributes with the attribute method for saving and deleting.
user.rb
has_one_attached :image
Or
has_many_attached :images
attribute :new_image
attribute :remove_image
attribute is a method that can be added as a read / write attribute in the model. I think there are various ways to save the image, but I took the method of saving in the model, so I added the model attribute with the attribute method.
Add before_save in the model.
user.rb
before_save do
if new_image
self.image = new_image
elsif remove_image
self.image.purge
end
end
When the image file is saved as described above, if there is new_image, it will be saved, and if there is remove_image, the file will be deleted. Use the purge method to delete the file.
Place the file field method on the form.
_form.erb
<%= form.label :new_image %>
<%= form.file_field :new_image %>
<% if @user.image.attached? %>
<%= image_tag @user.image.variant(resize: "128x128") %>
<%= form.check_box :remove_image %>
<%= form.label :remove_image %>
<% end %>
If you have an image file, you can delete it by checking the check box. The variant method of image_tag is a method that can be used only for image files, and you can adjust the size of the image file.
At this point, Active Storage will be used to save the file in the storage directory inside the application method.
Next, create an S3 bucket on AWS. First, create an AWS account. I will omit the detailed setting method, but after creating the root user, create an IAM user and attach a policy (AmazonS3FullAccess) to the IAM user as appropriate. Create an access key for this IAM user and write the access key ID and secret access key to credentials.
terminal
$ EDITOR="vim" rails credentials:edit
:credentials.yml.enc
AWS:
access_key_id:AWS access key
secret_access_key:AWS secret access key
Create a bucket as an IAM user. Select the S3 service and create a bucket from the bucket menu. Create a bucket by setting the bucket name, region, etc.
Add the gem to the Gemfile and do a bundle install.
Gemfile
gem 'aws-sdk-s3', require: false
Then edit config/storage.yml. Uncomment the part that says amazon: and fill in the necessary information.
storage.yml
test:
service: Disk
root: <%= Rails.root.join("tmp/storage") %>
local:
service: Disk
root: <%= Rails.root.join("storage") %>
# 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:Availability zone with S3
bucket:Bucket name
Call the access key etc. saved in credentials with Rails.application.credentials.dig (: aws,: ~).
Edit the config/environments/production.rb file.
production.rb
config.active_atorage.service = :amazon
Now you can save the file to S3 in the production environment.
If you edit the same part in the config/environments/development.rb file, you can save it in the S3 bucket in the development environment.
When handling multiple files with has_many_attached, you need to be careful about the form settings.
_form.erb
<%= form.label :new_images %>
<%= form.file_field :new_images %>
<% if @user.image.attached? %>
<% @user.images.each do |image| %>
<%= image_tag @user.image.variant(resize: "128x128") %>
<%= form.check_box :remove_image, {multiple:true}, image.id, false %>
<%= form.label :remove_images %>
<% end %>
When deleting the file, the controller processed it.
users_controller.rb
#abridgement
def update
#abridgement
if params[:user][:remove_images]
params[:user][:remove_images].each do |image_id|
image = @user.images.find(image_id)
image.purge
end
end
The installation itself was easy, so it was very convenient. I stumbled a lot because I need to be careful when dealing with multiple files. It is one of the systems that I definitely want to incorporate when dealing with files on AWS.
Let's use ActiveStorage + AWS S3 with Rails app! [Rails 5.2] How to use Active Storage
Recommended Posts