Rails Active Storage

What is Active Storage?

Active storage facilitates uploading files to cloud storage and attaching those files to Active Record objects.

Which storage services are supported?

Amazon S3, Google cloud, Microsoft Azure etc. as well as local disk-based service

Requirements

Various features of Active Storage depend on third-party software which Rails will not install, and must be installed separately:

Image analysis and transformations also require the image_processing gem.

$gem "image_processing", ">= 1.2"

Setup

$rails active_storage:install

$rails db:migrate

This will create 3 tables:

  • active_storage_blobs
  • active_storage_variant_records
  • active_storage_attachments - This is a join table joining model name and attachement for it.

Then update config/storage.yml which defines service names like local: amazon: gcs: digitalocean: etc.

When using certain services, special gems may need to be added e.g. $gem "aws-sdk-s3" etc.

Note: Configuration files that are environment-specific will take precedence: in production, for example, the config/storage/production.yml file (if existent) will take precedence over the config/storage.yml file.

Note: It is recommended to use Rails.env in the bucket names to further reduce the risk of accidentally destroying production data. e.g.

amazon:
  service: S3
  # ...
  bucket: your_own_bucket-<%= Rails.env %>

google:
  service: GCS
  # ...
  bucket: your_own_bucket-<%= Rails.env %>

Then update config/environments/development.rb to specify which service is used for Active storage.

e.g. 

# Store files locally.
config.active_storage.service = :local

or

# Store files on Amazon S3.
config.active_storage.service = :amazon

Attaching Files to Records

Use has_one_attached or has_many_attached inside a model. e.g.

Inside Model

class User < ApplicationRecord
  has_one_attached :avatar
end

Then inside controller, use

private
    def user_params
      params.require(:user).permit(:email_address, :password, :avatar)
    end

@user.avatar.attach(params[:avatar])

@user.avatar.attached?

Inside Model

class Message < ApplicationRecord
  has_many_attached :images
end

 

Inside Controller

class MessagesController < ApplicationController
  def create
    message = Message.create!(message_params)
    redirect_to message
  end

  private
    def message_params
      params.require(:message).permit(:title, :content, images: [])
    end
end

@message.images.attach(params[:images])

@message.images.attached?

How to attach images? Add following code to view erb.

<%= form.file_field :document %>

or

<%= form.file_field :documents, multiple: true %>

How to display images?

One attachment
<% if user.document.attached? %>
  <%= image_tag user.document %>
<% end %>

Multiple attachements
<% if user.documents.attached? %>
  <% user.documents.each do |document| %>
    <%= image_tag document %>
  <% end %>
<% end %>

How to debug?

$@client.logo.content_type

$@client.logo.content_type

$url_for(@client.logo)

$rails_blob_path(@client.logo, disposition: "attachment")

$rails_blob_path(@client.logo, only_path: true)

I found this Rails Active Storage cheatsheet useful.

 

Rating: