[RAILS] [Beginner] About Active Storage

Introduction

I am a beginner of programming learning for about 3 months for the first time, but I would like to keep a memorandum of what I learned in the Rails tutorial. This article was written with reference to the Rails tutorial.

What is Active Storage?

The most convenient way to upload files in Rails is to use a feature called Active Storage built into Rails. If you use this, you can easily create an image posting function etc. with a form. By using Active Storage in your application, you can use ImageMagick to transform image uploads, generate non-image upload image representations such as PDFs and videos, and extract metadata from arbitrary files.

Enable Active Storage

$ rails active_storage:install
$ rails db:migrate

This migration produces two tables named active_storage_blobs and active_storage_attachments. ` active_storage_blobsis the table where the actually uploaded files are stored, andactive_storage_attachments` is the intermediate table.

Add one file

This time, suppose you add one image to the Micropost model.

micropost.rb


class Micropost < ApplicationRecord
 has_one_attached :image
end

: image is the file name, please use whatever you like, such as: photo,: avatar, etc. according to the purpose of the file. The has_one_attached method is used to associate the specified model with the uploaded file. In this case, specify image to associate with the Micropost model.

Then add the file_fiele tag to the micropost form.

ruby:app/views/shared/_micropost_form.html.erb


<%= form_with model: @micropost, local: true  do |f| %>
  <%= f.text_area :content %>
  <%= f.file_field :image %>
  <%= f.submit %>
<% end %>

Finally, update the Microposts controller so that you can add images to the newly created micropost object. The Actuve Storage API provides a attach method for that, which you can use. Specifically, in the create action of the Microposts controller, attach the uploaded image to the @ micropost object. To allow this upload, you also need to update the micropost_params method to add: image to the allowed attributes list so that it can be updated via the web.

microposts_controller.rb


class MicropostsController < ApplicationController
 def create
    @micropost = current_user.microposts.build(micropost_params)
    @micropost.image.attach(params[:micropost][:image])
    if @micropost.save
      flash[:success] = "Micropost created!"
      redirect_to root_url
    else
      @feed_items = current_user.feed.paginate(page: params[:page])
      render 'static_pages/home'
    end
  end

  private

    def micropost_params
      params.require(:micropost).permit(:content, :image)
    end
 end

Once the image is uploaded, you can use the micropost partial'image_taghelper to draw (render) the associatedmicropost.image. Also, since the post may or may not have an image attached (only text without an image, etc.), is it a post with an image attached using a method that returns a logical value of attached?`? Check if the post is not attached, and if an image is attached, display the image.

ruby:app/views/microposts/_micropost.html.erb


 <%= image_tag micropost.image if micropost.image.attached? %>

Image verification

The above uploader has some noticeable drawbacks. In particular, there are no restrictions on uploaded images, so if a user raises a huge file or an invalid file, problems will occur. To fix this shortcoming, implement validation for image size and format. Active Storage does not natively support these formatting and validation features. So add a gem for Active Storage validation.

Gemfile


gem 'active_storage_validations'

Don't forget to run bundle install.

$ bundle install

If you read the documentation for this gem, you'll see that you can validate the image by inspecting the content_type as follows:

content_type: { in: %w[image/jpeg image/gif image/png],
                message: "must be a valid image format" }

This will check for images that correspond to the supported image formats.

Similarly, the file size can be validated as follows:

size: { less_than: 5.megabytes,
        message: "should be less than 5MB" }

This time, we will limit the size of the image to 5MB. Add these validations to your Micropost model.

micropost.rb


class Micropost < ApplicationRecord
 validates :image,   content_type: { in: %w[image/jpeg image/gif image/png],
                                      message: "must be a valid image format" },
                      size:         { less_than: 5.megabytes,
                                      message: "should be less than 5MB" }
end

In addition to these validations, we will also add a mechanism to check the size and format of image uploads on the client side (that is, the browser). Let's add a bit of JavaScript (specifically jQuery) and get an alert when the image the user is trying to upload is too big (this way the user wastes time uploading). You don't have to, and the load on the server is lighter).

ruby:app/views/shared/_micropost_form.html.erb


<script type="text/javascript">
  $("#micropost_image").bind("change", function() {
    var size_in_megabytes = this.files[0].size/1024/1024;
    if (size_in_megabytes > 5) {
      alert("Maximum file size is 5MB. Please choose a smaller file.");
      $("#micropost_image").val("");
    }
  });
</script>

This will warn you with the alert method if the file size is too large.

Finally, you can use the accept parameter in the file_field input tag to tell the user that you can only upload in a valid format.

ruby:app/views/shared/_micropost_form.html.erb


<%= f.file_field :image, accept: "image/jpeg,image/gif,image/png" %>

Only the valid image formats are initially selectable, and the other file types are grayed out.

Image resizing

To resize an image, you need a program to manipulate the image. This time we will use a program called ImageMagick, so install it in your development environment. (If your production environment is Heroku, you can already use` ImageMagick in your production environment.)

In the cloud IDE, you can install this program with the following command:

$ sudo apt-get -y install imagemagick

If you are not using a cloud IDE or equivalent Linux environment, the procedure for installing ImagiMagick will change depending on your environment. For example, if you are using a Mac, you must have Homebrew installed before you can install it with the brew install imagemagick command.

How to install for Homebrew

$ brew install imagemagick

Next, we need some gems for image processing. It requires image_processing gem and mini_magick gem, which is a Ruby ImageMagick processor.

Gemfile


gem 'image_processing'
gem 'mini_magick'
$ bundle install

You'll probably need to restart the Rails server after installation.

variat method

You will be able to create converted images with the variant method provided by Active Storage. In particular, use the resize_to_limit option to constrain the width and height of the image so that it does not exceed 500 pixels, as shown below.

image.variant(resize_to_limit: [500, 500])

Put this code in the display_image method separately for convenience.

micropost.rb


#Returns a resized image for display
def display_image
 imge.variant(resize_to_limit: [500, 500])
end

Now you can use display_image with micropost partials.

ruby:app/views/microposts/_micropost.html.erb


<%= image_tag micropost.display_image if micropost.image.attached? %>

Recommended Posts

[Beginner] About Active Storage
About Active Storage
About DelegationError (Active Storage)
Introduce Active Storage
[Rails] About active hash
Active Storage Initialization Manual
[Beginner] About Rails Session
[Swift] [Beginner]] About range operators
gem active_hash About active hash
Post videos with Active Storage
Move Active Storage on S3 locally
[Java beginner] About abstraction and interface
About =
Unit tests under Active Storage deployment
[Active Storage] Validation settings when uploading files
Rails Active Storage shrinks images before uploading
[Java beginner] About initialization of multidimensional array
Post / delete multiple images with Active Storage