gotoshin

主に学んだ事の自分メモ用です。記事に書くまでも無いような事はhttps://scrapbox.io/study-diary/に書いてます。

vue-dropzone × Active Storage で画像アップロード

実装したい機能

vue-dropzone × Active Storageを使って、画像を添付したらDBへアップロードされる機能を作成したい

環境

  • フロント:nuxt
  • バックエンド:Rails

アジェンダ

  1. 画像アップロード/フロント側
  2. 画像アップロード/バックエンド側
  3. アップロードした画像取得/バックエンド側

画像アップロード/フロント側

vue-dropzoneを使って実装する。

vue-dropzone導入方法

  • インストール
yarn add vue2-dropzone
  • 対象のcomponentにimport
import vue2Dropzone from 'vue2-dropzone'
import 'vue2-dropzone/dist/vue2Dropzone.min.css'
  • componentsに定義
export default {
  name: 'app',
  components: {
    vueDropzone: vue2Dropzone
  },

参考

Vue2-Dropzone

実装

<vue-dropzone
    id="dropzone"
    :options="dropzoneOptions"
    @vdropzone-success="successMethod"
>
</vue-dropzone>

各項目について

id
  • 書かないと警告が出たため必須
options

画像添付時の動作を指定可能。ここで画像保存用のエンドポイントを叩く

  data: function () {
    return {
      dropzoneOptions: {
        url: `${process.env.API_BASE_URL}/users/1`,
        thumbnailWidth: 150,
        maxFilesize: 0.5,
        paramName: 'image',
        method: 'put',
      }
    }
  },
url
  • APIのエンドポイントを指定可能。
  • 今回は元々あるuserレコードにputで画像を追加する
method
  • デフォルトはpostでputに変更する事も可能。
  • vue内のmethodを指定して呼び出す事も可能だが、画像添付時ではなく読み込み時に呼び出されるため、保存には不向き?。
paramName
  • パラメータ名を指定可能。
headers
  • ヘッダーを指定可能。今回は未使用だが、認証を使用している場合は使える。
maxFilesize
  • 添付画像の最大サイズ(MB)で指定する
maxFilesize
  • 添付画像の最大サイズ(MB)で指定する
thumbnailWidth
  • サムネイル画像の横幅
@vdropzone-success
  • 画像の添付に成功した際に呼び出す処理を指定出来る
  • これでDBに保存した画像のURLを取得する。
参照元

画像アップロード/バックエンド側

Active Storageを使って実装する。

Active Storage導入方法

installする

$ rails active_storage:install

テーブルを作る

$ rails db:migrate

active_storage_attachmentsactive_storage_blobsというテーブルを作成される

対象のmodelにActive Storageを定義する

class User < ApplicationRecord
  has_one_attached :image
end

以上。

controllerの実装

  • update scaffoldで作ったまんま。
  def update
    if @user.update(user_params)
      render json: @user
    else
      render json: @user.errors, status: :unprocessable_entity
    end
  end
  • user_params userモデルでhas_one_attached :imageと指定した事により あたかもimageカラムがあるかの様に扱う事が可能。
    def user_params
      params.permit(:image)
    end

アップロードした画像取得/バックエンド側

serializerActive Storage使って画像を取得する仕様にしました。

controllerの実装

scaffoldで作ったまんま特に編集無し。

    def set_user
      @user = User.find(params[:id])
    end
  def show
    render json: @user
  end

serializerの実装

class UserSerializer < ActiveModel::Serializer
  include Concerns::ImageUrl
  attributes :id,
  :image

  def image
    url_for(object.image) if object.image.attachment
  end

end

各項目について

ここの意味は?
object.image.attachment

active_storage_blobsobject.image.attachmentの2つのテーブルを生成したがそれぞれ

  • active_storage_blobs:ファイル名等のメタデータ
  • active_storage_attachments:画像データそのもの

が格納されている。 それぞれのテーブルにモデルからアクセス出来る。

  • active_storage_attachments/アクセス
object.image.attachment
  • 結果
#<ActiveStorage::Attachment id: 16, name: "image", record_type: "User", record_id: 1, blob_id: 17, created_at: "2020-03-07 13:23:45">
  • active_storage_blobs/アクセス
object.image.blob
  • 結果
#<ActiveStorage::Blob id: 17, key: "GF11mXbm3ZiUZtn2zZGVBQWW", filename: "bit201712121505387423.jpg", content_type: "image/jpeg", metadata: {"identified"=>true, "analyzed"=>true}, byte_size: 26108, checksum: "8VqE1O+XAr0PqHGGdxpMIg==", created_at: "2020-03-07 13:23:45">
ここの意味は?
url_for(object.image)

Active Storageで生成したカラムをurl_forメソッドに入れる事により、URLを生成する事が可能。 Active Storage の概要 - Railsガイド

url_helperを使えるようにするために

一手間必要でしたので、別記事にまとめてます。 Rails url_helperをSerializerで使いたい - hatehate-nazenazeのブログ

参考資料

  • vue-dropzone

Vue2-Dropzone

  • Active Storage

【Rails 5.2】 Active Storageの使い方 - Qiita