はじめに
はじめまして🏃
自分は現在プログラミングスクールでRuby on Railsを中心に勉強中の者です。
今回は学習する中で Active Storage が何をしてくれるのかを理解するのに苦労したので、初学者なりにまずは全体のイメージを掴むために整理してみました。
今回は全体のイメージ(流れ)をざっくり掴むのが目的なので、読んでて「補足したい・・!」と思われる部分が多くあると思いますが、そこはご了承ください・・・🙏
また、自分がプログラミング初学者のため、内容に誤りがあれば優しくコメントで教えてください🙇
概要
🔸Active Storageとは何者?
🔸Active Storageの導入方法
🔸Active Storageが提供する3つのテーブルについて(今回のメイン)
🔸説明しきれなかったこと
🔸まとめ
🔸Active Recode とは何者?
Railsガイドの説明はこう。
Active Storageは、Amazon S3、Google Cloud Storage、Microsoft Azure Storageなどのクラウドストレージサービスへのファイルのアップロードや、ファイルをActive Recordオブジェクトにアタッチする機能を提供します。 development環境とtest環境向けのローカルディスクベースのサービスを利用できるようになっており、ファイルを下位のサービスにミラーリングしてバックアップや移行に用いることも可能です。
Active Storageは、アプリケーションにアップロードした画像の変形や、PDFや動画などの画像以外のアップロードファイルの内容を代表する画像の生成、任意のファイルからのメタデータ抽出にも利用できます
分解してものすごくざっくり解釈するとこんな感じ💪
- ファイルをクラウドストレージやローカルディスクにアップロードできる。
開発環境やテスト環境の時 : ローカルディスク(自分のPC等)にファイルをアップロード。
本場環境の時: クラウドストレージサービスにファイルをアップロード。 - データ(ActiveRecordモデル)にファイルをアタッチ(添付・紐付け)できる。
- アップロードした画像の変形もできる。
- アップロードしたPDFや動画から代表画像を作れる。
- アップロードしてファイルからメタデータ(ファイルの詳細情報)を取り出せる。
🔸Active Storageの導入方法
以下の流れで整理していきます!
1、DBにテーブル作成
2、ファイルの保存先のストレージ設定
3、ファイルをモデル(レコード)に添付する
1、DBにテーブル作成
Active StorageはRails 5.2以降のバージョンに標準で組み込まれており、コマンドラインで以下の操作をすることで導入できる。
まずはActiveStorageに必要なマイグレーションを生成する。
rails active_storage:install
これによってActiveStorageが使用する3つのテーブルを作成するマイグレーションが生成される。(各テーブルの用途は後ほど説明します)
active_storage_blobs
active_storage_variant_records
active_storage_attachments
次に、マイグレーションを実行してDBに反映(先ほどの3つのテーブルを作成)
rails db:migrat
# 以下の3つのテーブルが生成される。
== 20210811020333 CreateActiveStorageTables: migrating ========================
-- create_table(:active_storage_blobs, {})
-> 0.1982s
-- create_table(:active_storage_attachments, {})
-> 0.0799s
-- create_table(:active_storage_variant_records, {})
-> 0.0805s
== 20210811020333 CreateActiveStorageTables: migrated (0.3589s) ===============
2、ファイル保存先のストレージを設定
Active Storageのサービスはconfig/storage.yml
で宣言する。
「アプリケーションが使うサービス」 ごとに、名前と必要な構成を指定する。
例えば以下の場合では、local
、test
、amazon
という3つのサービスを宣言している。
# config/storage.yml
local:
service: Disk
root: <%= Rails.root.join("storage") %>
test:
service: Disk
root: <%= Rails.root.join("tmp/storage") %>
amazon:
service: S3
access_key_id: ""
secret_access_key: ""
bucket: ""
region: "" # 例: 'ap-northeast-1'
Disk(ローカルストレージ)や、AWSのS3
、googleのGCS
、microsoftの`AzureStorageS3 等のクラウドストレージサービスの各詳細については割愛しますのでRailsガイドを参照ください🙇
クラウドストレージサービスを使う場合はgemの追加が必要のようです。
Railsガイド:組み込みのサービスアダプタ
次に、先ほど設定した利用サービスをActive Storageに認識させるため、Rails.application.config.active_storage.service
を設定していく必要がある。
使うサービスは環境ごと (開発・テスト・本番) に異なることもあるため、この設定を環境ごとに行うのが良いらしい。
-
development環境 でローカルDiskサービスを使うには、
config/environments/development.rb
に以下を追加!
# ファイルをローカルのディスクに保存する
config.active_storage.service = :local
-
test環境 でtestサービスを利用するには、
config/environments/test.rb
に以下を追加!
# ローカルファイルシステム上のアップロード済みファイルを一時ディレクトリに保存する
config.active_storage.service = :test
-
production環境 でAmazon S3を利用するには、
config/environments/production.rb
に以下を追加!
# ファイルをAmazon S3に保存する
config.active_storage.service = :amazon
3、ファイルをモデル(レコード)に添付する
ActiveStorageを使って画像などのデータを既存のテーブルと紐づけるために、モデルファイルに紐付け関連を追加する!
「1つのファイルを追加する場合」 と 「複数のファイルを追加する場合」 で分けて整理してみる。
ここでは添付する基本的な流れだけ整理するので、他の細かなオプションについては説明割愛します。実際はセキュリティ面から 「ファイルのサイズ」 や 「ファイルの形式」 等のバリデーション制限を設けることを検討する必要があります!
詳細はRailsガイドを見てください🙇
Railsガイド:ファイルをレコードに添付する
「1つのファイルを追加する場合」
has_one_attached マクロは、レコードとファイルの間に1対1のマッピングを設定する。
つまり、レコード1件ごとに1個のファイルを添付できる。
例えば、アプリケーションにUser
モデルがあるとして、
このUserモデルにuserアバター画像を添付したい場合は、以下のようにUser
モデルを定義ればいい。
class User < ApplicationRecord
has_one_attached :avatar
end
ビューのフォームを作成し画像を選択 → 登録or更新
<%=** form.file_field :avatar %>
コントローラーでフォームからのデータ(今回だとアバター画像ファイル)を受け取る。
class SignupController< ApplicationController
def create
@user= User.create!(user_params)
session[:user_id]= user.id
redirect_to root_path
end
private
def user_params
params.require(:user).permit(:email_address, :password, :avatar)
end
end
image_tagを使って画像を表示。
<%= image_tag @user.avatar %>
「複数のファイルを追加する場合」
has_many_attached マクロは、レコードとファイルの間に1対多の関係を設定する。
つまり、レコード1件ごとに多数の添付ファイルを添付できる。
例えば、アプリケーションにMessage
モデルがあるとして、
このMessageモデルに多数の画像を持たせるには、次のようなMessage
モデルを定義すればいい.
class Message < ApplicationRecord
has_many_attached :images
end
ビューのフォームを作成し画像を選択 → 登録or更新
<%= form.file_field :avatar, multiple: true %>
# multiple: trueオプションを付けることで複数ファイルの選択が可能になる。
コントローラーでフォームからのデータ(今回だとアバター画像ファイル)を受け取る。
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
# 値の受け取りは(image: [])とする。
image_tagを使って画像を表示。
<% @message.images.each do |image| %>
<%= image_tag message.image %>
<% end %>
ここでのポイントとしては、ファイルを添付したいモデルのテーブルにカラムを追加する必要がないということです。
各モデルのテーブルに新たにカラムを追加することなく、ファイルを添付できるのがActiveStorageの1つのポイント!👏
🔸Active Storageが提供する3つのテーブルについて
ここまで長くなりましたが、今回一番整理したかったのはこの部分です。🧐
ActiveStrageが提供する3つのテーブルについての用途がしっかり分かってなかったので、初学者なりにイメージをまとめてみました。
active_storage_blobs
active_storage_attachments
active_storage_variant_records
active_storage_blobs
このテーブルは、アップロードされた各ファイルのメタデータを保存する。
ファイル名、コンテンツタイプ、ファイルサイズ、ファイルの実体への参照(実体は別のストレージサービスに保存される)なんかが含まれる。
カラムはキー「key」、ファイル名「filename」、コンテンツタイプ「content_type」、ファイルサイズ「bute_size」、デジタル署名、作成時間などがある。
キーはストレージサービスでのファイルの場所を示す。
create_table "active_storage_blobs", charset: "utf8mb4", force: :cascade do |t|
t.string "key", null: false
t.string "filename", null: false
t.string "content_type"
t.text "metadata"
t.bigint "byte_size", null: false
t.string "checksum"
t.datetime "created_at", precision: nil, null: false
t.string "service_name", null: false
t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true
end
active_storage_attachments
このテーブルは実際のアプリケーションのモデルとアップロードされたファイル(blob)を関連付ける中間テーブルのようなもの。
このテーブルによって、どのモデルがどのファイルを参照しているか「接続」の管理がされている。
name, record_type, record_id, blob_idなどのカラムがあり、これらを使って関連付けが行われる。
record_typeカラム には関連付けられているモデル(Active Record モデル)のクラス名が格納され、これによりどのモデルがどのファイルを使用しているかが識別される。
create_table "active_storage_attachments", charset: "utf8mb4", force: :cascade do |t|
t.string "name", null: false
t.string "record_type", null: false
t.bigint "record_id", null: false
t.bigint "blob_id", null: false
t.datetime "created_at", precision: nil, null: false
t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id"
t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true
end
ActiveRecordによってモデルのオブジェクト(上の図だとUserオブジェクト)がDB上のデータにマッピングされているように、Blobオブジェクトがローカルまたはクラウドストレージ上のファイルにマッピングされている。
このおかげで主モデル(上の図だとUser), Attachment, Blobモデル間の関連付けにより、モデル(Userオブジェクト)と添付ファイルを紐付けることができるようになっている。🧐
active_storage_variant_records
このテーブルは元の画像から派生したバリアントの情報を保存する。
バリアントとは、元の画像から生成された異なるバージョンのことで、例えば、サムネイル画像やリサイズされた画像なんかが該当する。
Active Storageは元の画像を変更せずに、異なるサイズやフォーマットの画像バリアントを作成できる。
このテーブルは、そのバリアントの情報を保存する。
通常、アプリケーション内で直接操作する必要はありませんが、Active Storage によって内部的に使用される。
create_table "active_storage_variant_records", charset: "utf8mb4", force: :cascade do |t|
t.bigint "blob_id", null: false
t.string "variation_digest", null: false
t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true
end
🔸説明しきれなかった大事なこと
以下については触れてないので、またまたRailsガイドを見てください!🙇
全然まとめれてなくてすみません・・・🙇
Railsガイド:active-storageについて
- ファイルに対するバリデーションについて。(セキュリティ面で必須)
- variantメソッドによる画像の変形(サイズ変更等)。
- purgeメソッドによるファイルの削除。
- downloadメソッドによるファイルのダウンロード
- analyze?メソッドによるファイルの解析
- representationメソッドによる画像、動画、PDFの表示
- その他
🔸まとめ
まだ自分でアプリを作成して採用するような作業まではできていないので、かなり大雑把なまとめになりましたが、全体的な機能のイメージはできた気はするので、実際に導入してみて慣れていきたいです。
しかし、調べていく中で「CarrierWave」と「Active Storage」のどちらが良いか?という意見があったので、導入する際には調査・検証して判断していく必要がありそうです。
【今回見てきたActiveStorageは以下の特徴】
- モデルに新たなカラムを追加せずにファイルを添付できる。
- 開発環境、テスト環境、本番環境で異なるストレージサービスを利用することが容易になる。
- 画像変換や動画変換などの処理も行える。(今回ほぼ触れてませんが・・・)
初学者にはRailsガイドを読むことに若干抵抗がありますが、「ここに基本の全てが書いてある!」と言う方も多いので、新しい技術に出会った際は逃げずに時間をかけてでも読み込んでいきたいです。
🔸参考
Active Storage の概要 - Railsガイド
Active Storageを使用したRailsにおけるファイルアップロードの方法 | みぎさんドットコム
Active Storageを使って画像をアップしよう!
【Rails】ActiveStroageの使い方を実例で解説|複数画像やファイルのアップロードと個別に削除・変更する方法
[Rails5.2]ActiveStorageの仕組み(図あり)と使ってみてわかったこと - Qiita