note: 2020.12.29追記
私の書いた記事の中では比較的人気なこの記事なのですが、実は、このQiita記事を見つけて以来、自分では参照もしないし、人に紹介もしたりしないようにしています。
個人的には、あまり良い実装ではないように思いますので、よろしければ一度下記の記事をお読みになって、それでも「やってみたい!」と思われた方は参照されてみてください。
ActiveRecord serialize / store の甘い誘惑を断ち切ろう
何をしたか
CarrierWaveで複数画像をアップロードする機能を作りたいと思います。
Imagesテーブルを別途作って多対多のアソシエーションを結ぼうかとも考えていたのですが、こちらの記事で、CarrierWaveが複数画像のアップロードに対応していることを知り、
CarrierWave 複数の画像をコード三行で一つのカラムに保存する
この記事が参照している公式ドキュメントのMultiple Uploadの項目を元に、実装を進めていきました。
個人的にはかなりつまづいたので、備忘も兼ねてメモします^^
テーブルに画像のカラムを追加する
テーブルに(今回はworks
)画像をアップロードするカラム(今回はimages
)を追加します。カラム名を複数形にするのを忘れないでください。
rails g migration add_images_to_works images:string
rails db:migrate
データベースがjsonのデータ型をサポートしている場合(PostgreSQL, MySQLなど)はデータ型をJSONにし、images:json
と表記します。
モデルにmount_uploaderメソッドを記載する
CarrierWaveでは、mount_uploaderというメソッドを使ってimages_uploader
とモデルを紐づけるのですが、
(↑この説明がピンとこない人は、拙著ですがこちらの記事をご覧ください。「HerokuでS3に画像をアップロードした話[Rails][S3][CarrierWave][fog]
Rails」)
今回はモデルに以下のような記述をします。
class Work < ActiveRecord::Base
mount_uploaders :images, ImageUploader
serialize :images, JSON # SQLiteを使っているときはこの列を追記
end
mount_uploaders
とsがついて複数形になっているのを見逃さないでください。
serializs :works, JSON
の部分は、まだ理解が十分でないのですが、複数のデータをハッシュの形にして1カラムに保存するための既述のようです。
view, controllerを調整する
これらのデータを保存/取り出すために、viewの記載は以下のように変更します。
アップロードする際には、multiple: true
を記載し、複数ファイルを扱えるようにします。
= f.file_field :images, multiple: true
imageを取り出す箇所では、何番目のイメージを取り出すか記載します。
= image_tag work.images[0].url
また、controllerのparamsは以下のように空の配列をハッシュの中に記載します。
params.require(:work).permit(:name, {images: []}, :description)
以上で、複数のimageがアップロードできるようになりました!
なお、本番環境(Heroku)ではデータベースがPostgreSQLなので、そのまま動くか心配でしたが、私の場合、上記の設定でアップロードしても大丈夫でした。
ご意見、修正事項あればいただけましたら嬉しいです^^