ActiveStorageとは何か?

ActiveStorageとは?

Active Storageとは、ファイルアップロードを簡単に実装できるgemです。railsの標準のgemで、rails5.2から追加されました。

以前は、CarrierWaveというgemが使われていましたが、Rails5.2からはActiveStorageが使われることが多くなりました。

ユーザー側から、画像などのファイルをサーバーにアップロードして、サーバーにおいてあるファイルをモデルが取得するためにActiveStorageが使われます。また、サーバーではなく、Amazon S3, Google Cloud Storage, Microsoft Azure Storageなどのクラウドストレージサービスに対してファイルをアップロードすることもできます。

例)

SNSを使って、写真や画像を投稿する時、(=画像ファイルをアップロードする時)ActiveStorageを使って、画像ファイルを保存している。保存した場所(サーバーやクラウドストレージサービス)から、取り出してきて、見えるように表示している。

ActiveStorageの導入

#gemのインストールはRailsインストール時に行われているので、不要。
$ rails active_storage:install
#=>コマンド実行時に、active_storage_blobs とactive_storage_attachmentsという2つのテーブルを作成するマイグレーションファイルが生成されます。

#migrationファイルをDBに反映させる。
$ rails db:migrate

active_storage_blobsは実際にアップロードしたファイルが保存されるテーブル(実際はファイル名、ファイルの種類、バイト数、誤り検出符号などのファイルデータを保持するテーブル)で、active_storage_attachmentsは実際に操作を行うモデルとactive_storage_blobsを紐づける中間テーブルになります。

ファイルの保存場所を管理する設定の仕方

設定はRails .application .config .active _storage.serviceにファイルを保存する場所を名前で指定し、そのファイルの保存場所の名前に対応する設定をconfig/storage.ymlに定義することで行います。

#ファイルを保存する場所をlocalに設定
#デフォルトではdevelopment環境のファイルの管理場所はlocalとなっている
config.active_storage.service = :local
test: #testにおいてあるファイルの設定方法。ここで、testを定義している。
  service: Disk #testの時は使用するサービスをローカルディスクに設定
  root: <%= Rails.root.join("tmp/storage") %> #ファイルを格納する場所

local: #localにおいてあるファイルの設定方法(デフォルト)。ここで、localを定義している。
  service: Disk #localの時は使用するサービスをローカルディスクに設定
  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: us-east-1
#   bucket: your_own_bucket

# Remember not to checkin your GCS keyfile to a repository
# google:
#   service: GCS
#   project: your_project
#   credentials: <%= Rails.root.join("path/to/gcs.keyfile") %>
#   bucket: your_own_bucket

# Use rails credentials:edit to set the Azure Storage secret(as azure_storage:storage_access_key)
# microsoft:
#   service: AzureStorage
#   storage_account_name: your_account_name
#   storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %>
#   container: your_container_name

# mirror:
#   service: Mirror
#   primary: local
#   mirrors: [ amazon, google, microsoft ]

ここのファイルに書いてある情報(ルート、サービスなど)をもとに、モデルが実際のファイルを取得しに行きます。 Active Storageではローカルの他にも様々なサービスを指定することができます。 コメントアウトされている部分をみるとAWSのS3googleのGCSmicrosoftのAzureStorageも使うことができます。使う場合はこちらのコメントアウトを外し、Gemfileに対応したgemを追加する必要があります。

# Active Storageで指定できるservice
AWS    aws-sdk-s3 # 使用できるgem
google  google-cloud-storage # 使用できるgem
microsoft   azure-storage # 使用できるgem

モデルと添付ファイルを紐づける(1つの添付ファイルの場合)

class Task < ApplicationRecord
    # has_one_attachedを使って、Taskモデルに1つの画像を添付する
  has_one_attached :image #imageはファイルの呼び名のこと
end

:imageはファイルの呼び名で、:photo:avatar:hogeなど、ファイルの用途に合わせて好きなものを指定できます。以上のように指定することで、active storageが自動でBlobとAttachmentの2つのテーブルを使って、モデルからimageファイル(カラム)を取得できるようにしてくれます。

ここで、指定しているのは画像ファイル(:image)ですが、モデルに指定することで、まるでモデルのカラムであるかのように扱うことが出来ます。

つまり、imageというカラムで画像ファイルimageを保存しているイメージです。

モデルと添付ファイルを紐づける(複数の添付ファイルの場合)

# 複数の画像ファイルを一つのタスクに紐づける場合,has_one_attachedの代わりにhas_many_attachedを使う
class Task < ApplicationRecord
  has_many_attached :images
end

has_one_attachedとhas_many_attached

  • **has_one_attached** = レコードとファイルの間に1対1のマッピングを設定します。各レコードには1つのファイルを添付できます。

例)1つのメッセージに1つの画像ファイルを紐づける時に使用します。 - **has_many_attached** = レコードとファイルの間に1対多の関係を設定します。各レコードには、多数の添付ファイルをアタッチできます。

例)1つのメッセージごとに複数の画像ファイルを紐づける時に使用します。

保存したファイルを表示させるために、ビューを編集する

# カラムとして扱っている画像ファイルを表示する
<%= image_tag user.image %>

#画像の大きさを調節するためにvariantメソッドを使用する
# 画像の幅を統一したい場合はvariantメソッドを使用
# 200x200のサイズで画像が表示
<%= image_tag user.image.variant(resize:'200x200') %>

画像を削除する

# 画像を削除するにはpurgeメソッドを使う
user = User.find(params[:id])
user.image.purge

画像の大きさを調節する

デフォルトでは、画像は元のファイルのサイズのままであり、サイズを変更したい場合は、設定が必要になる。

# ImageMagickという画像変換ツールをインストール
$ brew install imagemagick
# ImageMagickをrailsで使えるようにするためmini_magickというgemをインストール
gem 'mini_magick'
#この後、bundle installコマンドをうつ
# 画像の幅を統一したい場合はvariantメソッドを使用
# 200x200のサイズで画像が表示
<%= image_tag user.image.variant(resize:'200x200') %>

ビューなどに画像ファイルを表示する記述を書いたとしても、StrongParametersを設定していた場合、アップロードしたファイルの情報を無視せず表示するために、新たに許可するパラメータのキーを設定し直す必要があります。

# 許可するパラメータのキーとして:imageを追加
def task params
    params.require(:task).permit(:name, description, :image)
end

ActiveStorageのメソッド

attachメソッド

レシーバーのオブジェクトに対して、指定のファイルを直接紐付けるメソッドです。

# 既存のメッセージに新しい画像を追加
@message.images.attach(params[:images])

attached?メソッド

レシーバのオブジェクトに指定のファイルが紐付いていればtrueを紐付いていなければ、falseを戻り値として返すメソッドです。

# あるメッセージに何らかの画像が添付されているかどうかを調べる
@message.images.attached?

variantメソッド

画像を変換する際に使われるメソッドです。このメソッドを使うためには、image_processing gemGemfileに追加する必要があります。

# ブラウザがバリアントURLにヒットすると、Active Storageは元のblobを指定のフォーマットに遅延変換し、新しいサービスのロケーションにリダイレクトします。
# 画像ファイルを100 * 100のサイズに変換する
<%= image_tag user.avatar.variant(resize: "100x100") %>

参照

【Rails 5.2】 Active Storageの使い方 - Qiita

CarrierWaveチュートリアル

Active Storageを使って画像をアップしよう!

Active Storage の概要 - Railsガイド