【Rails】Active Storageを使って画像をアップロードする
実装したいこと
以前、gem
のCarrier Wave
を使って画像アップロード機能を実装しました。
今回は試しにActive Storage
を使用してみたいと思います。
初めて使ったのですが、すごく簡単でした。
ただし、ファイルの形式のバリデーションやデフォルト画像の設定などの機能はついてないので不便さも感じました。
Active Storageとは
Rails5.2
から提供されるようになったファイルアップロード機能
実装の流れ
- Active Storageのセットアップ
- ファイルをアップロードしたいModelの設定
- Viewの設定
- Contorollerの設定
Active Storageのセットアップ
$ rails active_storage:install
このコマンドでマイグレーションファイルが生成されるので、ターミナルでrails db:migrate
します。
# 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 t.foreign_key :active_storage_blobs, column: :blob_id end end end
生成されるテーブルはそれぞれ、ActiveStorage::Attachment
と ActiveStorage::Blob
モデルに紐付いています。
ActiveStorage::Blob
は、アップロードした画像についての情報を管理するモデル
ActiveStorage::Attachment
は、画像を扱う他のモデルとActiveStorage::Blobを結びつける中間テーブル的なモデル。ポリモーフィック関連となっている。
アップロードしたファイルの保存先設定
config/environments/development.rb
でファイル管理場所を指定できます。
#33行目あたり # Store uploaded files on the local file system (see config/storage.yml for options). config.active_storage.service = :local
今は、local
が指定されています。local
とはどこなのか更にみていきます。
コメント部分にあるように、config/storage.yml
を確認します。
test: service: Disk root: <%= Rails.root.join("tmp/storage") %> local: service: Disk root: <%= Rails.root.join("storage") %>
service: Disk
でローカル環境にファイルが保存される設定になっています。
今回はデフォルトの設定のまま進めていきます。
Model
今回は、Postモデルで画像を扱えるようにします。
各投稿に1つの画像を添付できるようにしたいので、has_one_attached
メソッドを使います。
多数添付したいときは、has_many_attached
を使います。
class Post < ApplicationRecord belongs_to :user has_one_attached :image #ここ (略) end
Views
入力フォームを整えていきます。
= form_with model:@post, local: true do |f| (略) .form-group = f.label :image = f.file_field :image, class: 'form-control' = f.submit nil, class: 'btn btn-primary'
画像を表示したい部分には以下のコードを使います。
= image_tag post.image.variant(resize_to_limit: [300,200]) if post.image.attached?
image_tag
は、画像が添付されていないときはエラーになるので、if
で判定文をつけてあげます。
variant(resize_to_limit: [300,200])
でサイズを指定しています。
この機能を使いたい場合は、Gemfile
の以下のgem
のコメントアウトを外す必要があります。
# Use Active Storage variant gem 'image_processing', '~> 1.2'
Contoller
Strong Parameterで弾かれないように、image
のパラメーターも許可するように設定しておきます。
(略) def post_params params.require(:post).permit(:title, :body, :image) end