はじめに
フロントエンドにNuxt.js、バックエンドにRails APIモードでの画像ファイルを含む内容を保存させるときにやることの記事です。
Nuxt.js、Railsはそれぞれ構築済みであることとします。
必要なもの
gem carrierwave
実装方法
Rails
1. Gemfileにcarrierwave
を追記しターミナルでbundle install
します。
...途中省略
gem 'carrierwave', '~> 2.0'
bundle install
2. アップローダークラスの生成
ターミナルで下記コマンドを実行してアップローダークラスを生成します。
bundle exec rails g uploader アップローダー名(大文字始まり)
実行すると、/app/uploaders/アップローダー名_uploader.rb
が生成されます。
Image
の場合は下記のようになります。
bundle exec rails g uploader Image
3.アップロードする画像のカラムをテーブルに追加します。
アップロードする画像情報を保存するカラムをテーブルに追加するマイグレーションファイルを作成します。
ターミナルで下記コマンドを実行します。
bundle exec rails g migration add_カラム名_to_テーブル カラム名:string
マイグレーションファイルが作成されたら、ターミナルでマイグレーションを実行します。
bundle exec rails db:migrate
追加したカラムをコントローラのプライベートメソッドに追記します。
module V1
class ***Controller < ApplicationController
...途中省略
def create
*** = ***.create!(***_params)
if ***.save
render json: ***
else
render json: ***.errors
end
end
private
def ***_params
params.require(:***).permit(:カラム名, :カラム名, :追加したカラム名)
end
end
end
4.アップローダークラスとカラムを紐付けます。
class モデル名 < ApplicationRecord
mount_uploader :追加したカラム名, アップローダークラス
end
5..gitignoreに/public/uploads
を追記します。
保存に成功した画像ファイルは/public/uploads
に置かれるので、Git管理下から除外するため.gitignore
に追記します。
Nuxt.js
フロントエンドは親コンポーネントと子コンポーネントに分けます。
<template>
<AddImage @submit="addImage" />
</template>
<script>
import AddImage from '~/components/AddImage'
import axios from '~/plugins/axios'
export default {
compoponents: {
AddImage,
},
methods: {
async addImage(formData, config) {
await axios.post('バックエンドエンドポイント', formData, config)
.then(() => {})
.catch(() => {})
}
}
}
</script>
<template>
<v-form>
<v-container>
<v-row>
<v-col
cols="12"
md="4"
>
<div>
<v-file-input
label="image"
accept="image/*"
v-model="addImage"
prepend-icon="mdi-camera"
/>
</div>
</v-col>
<v-col
cols="12"
md="4"
>
<v-btn
@click="handleSubmit"
>
作成
</v-btn>
</v-col>
</v-row>
</v-container>
</v-form>
</template>
<script>
export default {
data () {
return {
addImage: []
}
},
methods: {
handleSubmit() {
const formData = new FormData()
formData.append('key', this.addImage)
const config = {
headders: {
'content-type': 'multipart/form-data'
}
}
this.$emit('submit', formData, config)
}
}
}
</script>
子コンポーネントの「作成」ボタンをクリックするとhundleSubmit
が動き、emitを使用して子コンポーネントから親コンポーネントへデータを渡しています。
最後に
参考させていただいた記事をまとめます。
【Rails】 CarrierWaveチュートリアル
Vuetifyのv-file-inputで画像を送信する方法