はじめに
syomaと申します。よろしくお願いいたします。
某プログラミングスクールの最終課題で某フリマアプリのクローンにて、商品出品における画像の複数投稿のための下準備でcarrierwaveとMiniMagickを導入しました。
環境
Rails 5.2.4.1
ruby 2.5.1
やりたいこと
- carrierwaveの導入
- MiniMagickの導入
0.下準備
複数画像を投稿する場合は?対多(画像)になるので、Photoテーブルを作成し、カラム名はimageにしようと思います。※1枚のみであれば保存したいテーブルにimageカラムを追記するだけでOK!
保存先のテーブルを用意しましょう
以下のコマンドを実行してPhotoモデルを作成してください。
$ rails g model Photo
作成できたら、下記のファイルを記述を変更します。
class CreatePhotos < ActiveRecord::Migration[5.2]
def change
create_table :photos do |t|
# ==========ここから追加する==========
t.string :image, null: false
t.references :good, foreign_key: true, null: false
# ==========ここまで追加する==========
# t.references :good, foreign_key: true, null: falseのgoodは
# 紐付けたいテーブル名です。私の場合は商品に紐付けたかったのでGoodテーブルに紐づけております。
# 人によってはテーブル名が異なるかと存じます。
t.timestamps
end
end
end
では、マイグレーションファイルを実行してphotosテーブルを作成します。
$ rails db:migrate
アソシエーションの設定
モデルを作成したらアソシエーションの設定を行います。
アソシエーションとは、2つのモデル同士のつながりを指します。モデルとモデルの間には関連付けを行う必要があります。GoodモデルとPhotoモデルのアソシエーションを設定します。上記2つのモデルの関係性は以下のようになります。
- 一つの商品は複数の写真を持つことができる
- 写真Aに関して、写真Aに紐づく商品は一つしかない
つまり、GoodモデルとPhotoモデルは「1対多」の関係になります。
では、app/models/good.rbに以下のコードを追加してください。
has_many :photos, dependent: :destroy
次にapp/models/photo.rbに以下のコードを追加してください。
belongs_to :good
これで、アソシエーションの設定は完了です。
1. carrierwaveの導入
carrierwaveはファイルを簡単かつ柔軟にアップロードする方法を提供するgem。
carrierwaveのGemをインストール
gem "carrierwave"
$ bundle install
CarrierWaveのアップローダーを作成
$ rails g uploader Image
上記のコマンドを実行すると以下のファイルが作成されます。
create app/uploaders/image_uploader.rb
image_uploader.rbでは、ファイルの保存方法(デフォルトはファイル)、保存パス、ファイルのサイズ、拡張子やファイル名の変換などが変更できます。
モデルのカラムにアップローダーを紐付け
Photoモデルのimageカラムと、先ほど作成したアップローダーImageUploaderと紐付けをします。(ImageUploaderはapp/uploaders/image_uploader.rbのクラスの名前です。)
app/models/photo.rbに以下のコードを追加してください。
class Photo < ApplicationRecord
belongs_to :good , optional: true
# ==========ここから追加する==========
mount_uploader :image, ImageUploader
# ==========ここまで追加する==========
end
2.MiniMagickの導入
MiniMagickは画像をリサイズできるgemです。Gemfileの最下部に以下のコードを追加します。
gem "mini_magick"
$ bundle install
アップローダーの記述を修正
app/uploaders/image_uploader.rbを修正します。
ここで修正するのは以下の3点です。
- 4行目のすでに生成されているコードのコメントを外す
- 「version :middle」というサイズを指定するコードを追加 ※サイズを指定しない場合は不要
- extension_whitelistメソッドのコメントアウトを外す
class ImageUploader < CarrierWave::Uploader::Base
# Include RMagick or MiniMagick support:
# include CarrierWave::RMagick
include CarrierWave::MiniMagick # ここのコメントアウトを外す
# Choose what kind of storage to use for this uploader:
storage :file
# storage :fog
# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
# Provide a default URL as a default if there hasn't been a file uploaded:
# def default_url(*args)
# # For Rails 3.1+ asset pipeline compatibility:
# # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
#
# "/images/fallback/" + [version_name, "default.png"].compact.join('_')
# end
# Process files as they are uploaded:
# process scale: [200, 300]
#
# def scale(width, height)
# # do something
# end
# Create different versions of your uploaded files:
# version :thumb do
# process resize_to_fit: [50, 50]
# end
# ==========ここから追加する==========
version :middle do
process resize_to_fill: [188, 188]
end
# ==========ここまで追加する==========
# Add a white list of extensions which are allowed to be uploaded.
# For images you might use something like this:
# ここのコメントアウトを外す
def extension_whitelist
%w(jpg jpeg gif png)
end
# Override the filename of the uploaded files:
# Avoid using model.id or version_name here, see uploader/store.rb for details.
# def filename
# "something.jpg" if original_filename
# end
end
version :middle do
process resize_to_fill: [188, 188]
end
middleというバージョンが作成され、画像を188 x 188ピクセルにリサイズします。
最後に
実際の投稿は
【Ajax+Rails+Carrierwave】個別削除可能な画像複数(10枚まで)投稿
https://qiita.com/syoma/items/09a0d7bbadad35771a4d
にてご案内しております。もし、参考になったと思ったら「いいね」よろしくお願いいたします!
twitterもやっておりますので是非フォローよろしくお願いいたします。
https://twitter.com/syomabusiness
youtubeも始める予定です。