Just do IT

思うは招く

ActiveStorageを使って画像アップロード機能を実装してみる

やりたいこと

ActiveStorageを使い、Railsアプリに画像をアップロードする機能をつけたい(development環境)。

環境

試作アプリをつくる

active_storageというRailsアプリを作る。 続いて、簡単なブログ機能を作成し、マイグレーションも実行する。

rails new active_storage
cd active_storage
bin/rails g scaffold blog title:string memo:text
bin/rails db:migrate

サーバーを起動し、表示されるか確認する。

bin/rails s

以下にアクセス。

http://localhost:3000/blogs

簡易的なブログができた。

f:id:K_Koh:20200227092428j:plain

次に、ActiveStorageを使ってブログ記事に画像を投稿できるようにしてみる。

ActiveStorage

Rails5.2以降でActiveStorageは標準装備になった。 あらたにgemをインストールする必要はなく、以下のコマンドでRailsアプリ内で使えるようにしてあげればよい。

bin/rails active_storage:install
Copied migration 20200227002536_create_active_storage_tables.active_storage.rb from active_storage

とあるマイグレーションファイルが作成された。

マイグレーションを実行すると、active_storage_blobsとactive_storage_attachmentsという名前の2つのテーブルが作られる。

  • active_storage_blobs
    • 添付されたファイルに対応するモデル
    • ファイル名やメタデータ、サイズなどを管理
  • active_storage_attachments
    • active_storage_blobsとアプリ内の他のモデルを関連付ける中間テーブル

たとえば、blogsテーブルに画像を保存したい場合、active_storage_attachmentsを介して、active_storage_blobsと関連づく。

マイグレーションを実行。

bin/rails db:migrate

設定

アップロードした画像ファイルの保管についての設定をするため、次の2ステップをおこなう。

  • Rails.application.config.active_storage.serviceにファイルを管理する場所の名前を設定する
  • ファイルの管理先の名前をconfig/storage.ymlに定義する

development環境の場合、デフォルトのまま何も変える必要はない。

config/environments/development.rb

  # Store uploaded files on the local file system (see config/storage.yml for options).
  config.active_storage.service = :local

config.active_storage.serviceにはlocalが指定されている。

config/storage.yml

test:
  service: Disk
  root: <%= Rails.root.join("tmp/storage") %>
local:
  service: Disk
  root: <%= Rails.root.join("storage") %>
# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
~
~

これでstorageディレクトリに画像が保存されるということになる。

モデルを修正

Blogモデルに以下を追記。

app/models/blog.rb

class Blog < ApplicationRecord
  has_one_attached :image
end

これで、Blogモデルからimageで画像を参照できる。

ストロングパラメーターを修正

画像を保存できるようにはなったが、これだとストロングパラメーターに引っかかるため、画像も通るようにする。

app/controllers/blogs_controller.rbに、:imageを追記。

~
~
  private
~
~
    # Only allow a list of trusted parameters through.
    def blog_params
      params.require(:blog).permit(:title, :memo, :image)
    end

ビューを修正

formやshowファイルなどにimageを登録、表示させる記述をする。

app/views/blogs/_form.html.erb

~
~
  <div class="field">
    <%= form.label :memo %>
    <%= form.text_area :memo %>
  </div>
  
  # 追記
  <div class="field">
    <%= form.label :image %>
    <%= form.file_field :image %>
  </div>
~
~

app/views/blogs/show.html.erb

<p>
  <strong>Image:</strong>
  <%= image_tag(@blog.image) if @blog.image.present? %>
</p>

画像を表示したいのでimage_tagヘルパーを使う。 if @blog.image.present?で「もし記事に画像があれば表示してよね」とRailsに指示している。

サーバーを起動

サーバーを起動し、画像をアップロードしてみる。 画像が添付できるようになっている。

f:id:K_Koh:20200227095956j:plain

適当に記事を作り、画像をアップすると、

f:id:K_Koh:20200227100058j:plain

画像が表示された!

参考

Active Storage の概要 - Railsガイド