画像アップロード機能「Active Storage」を使ってみた!
「Active Storage」とは
Rails5.2から登場したgemで、ActiveRecordモデルへの紐付けや、
クラウドストレージサービス(AWS、GCP、Azure)へアップロードが非常に容易に行えるライブラリ。
現在は、画像アップロードには「CarrierWave」というgemが一番よく使われているが、
今後はこの「ActiveStorage」が使われることになると言われている。。。(本当?)
1. ActiveStorageを準備する
gemをインストールするためには以下のコマンドを実行します。
rails active_storage:install
そうすると、以下のようなマイグレーションファイルが作成されます。
xxxxxxxxxxxxxxxxx_create_active_storage_tables.active_storage.rb
このマイグレーションファイルの中身は以下のようになっています。
# This migration comes from active_storage (originally 20170806125915) class CreateActiveStorageTables < ActiveRecord::Migration[5.2] def change create_table :active_storage_blobs 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, null: false t.datetime :created_at, null: false t.index [ :key ], unique: true end create_table :active_storage_attachments do |t| t.string :name, null: false t.references :record, null: false, polymorphic: true, index: false t.references :blob, null: false t.datetime :created_at, null: false t.index [ :record_type, :record_id, :name, :blob_id ], name: "index_active_storage_attachments_uniqueness", unique: true end end end
この中身を見ると、テーブルが2つ作成されていることがわかります。
それぞれどういう役割を果たすかを簡単に説明すると、以下のようになります。
・active_storage_blobs ・・・ ActiveStorage::Blobというモデルと紐づいており、ファイルの実態以外の情報(識別キー、ファイル名、Content-type、ファイルのメタデータ、サイズ等)を管理するもの
・active_storage_attachments ・・・ ActiveStorage::Attachmentというモデルと紐づいており、ActiveStorage::Blobとその他のモデルを繋げる中間的な役割を果たすもの
作成されたマイグレーションファイルは特にいじらずにマイグレートを実施します。
rails db:migrate
次にファイルの実態をどこで管理するか設定している箇所を見てきます。
config/environments/development.rb
test: service: Disk root: <%= Rails.root.join("tmp/storage") %> local: service: Disk root: <%= Rails.root.join("storage") %>
「root: <%= Rails.root.join("storage") %>」という記述がありますが、
この部分がファイルの実態の保管場所を意味しています。(root直下のstorageディレクトリ)
2. 画像アップロードを実装する
models/post.rbの中に「 has_one_attached :image」を追記します。
例では、Postモデルに紐付けをしたかったので、post.rbの中に記述しました。
このように「ActiveStorage」をインストールし、テーブルを作成してしまえば、
他のテーブルは修正することがなく、下記のような一文でテーブル間の連携ができてしまいます。(めちゃ楽)
1ポスト1画像を紐付けたかったため、「has_one_attached」としましたが、
もし複数の画像を紐付けたい場合は「has_many_attached」を使えば良いです。
class Post < ApplicationRecord has_one_attached :image end
アップロード機能の実装は普通の画像アップロードと変わりません。
<% f.label :image %> <%= f.file_field :image, class: 'form-control' %> end
あとは、アップロードした画像を表示させます。
<% if @post.image.attached? %> <%= image_tag @post.image %> <% end %> end
「image.attahed?」メソッドを使うことで、画像が添付されていない場合でもエラーを回避することができます。
(image_tagは画像がない場合エラーを表示する。)