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