##Gemのインストール
gem 'carrierwave'
gem 'rmagick'
画像投稿機能に関わるgemのインストールをお忘れなく。
gem'rmagick'は画像のリサイズなどに使用します。
##前置き
rails g uploader images
リサイズなど画像の設定をする為のファイルが生成されます。
app/uploaders/images_uploader.rb
##モデルとの紐付け
imageが存在するモデルをItem_Imageモデルとしています。
ItemImagesテーブルとItemsテーブルは1対多の関係にあります。
画像は沢山のItemを持っているからです。
class Item < ApplicationRecord
has_many :item_images
accepts_nested_attributes_for :item_images
end
ネストさせるパラメータ(item_imageモデル)の親のモデルクラスであるitemモデルにaccepts_nested_attributes_forを記述します。引数にはネストの子のモデルをシンボルで指定してあげます。
has_manyなので複数形で記述します。
こうすることで item_images_attributesメソッドがItemモデルに追加されました。
後ほど使用します。
class ItemImage < ApplicationRecord
belongs_to :item
mount_uploader :image, ImageUploader
end
ItemImagesテーブルに追加したカラムの名前をmount_uploaderに指定します。
##Itemsコントローラーの設定
def new
@item = Item.new
@item_image = @item.item_images.build
end
formで使用する@itemをnewメソッドで生成し、
buildメソッドでitemモデルに紐付くitem_imageモデルを生成しています。
buildメソッドは慣習的に、関連するモデルを生成するときは、buildを使うようです。
ここで生成したインスタンス変数@item_imageはcreateメソッドで使用します。
##Formの作成
= form_with(model:@item, locale: true , id: 'new_item') do |f|
= f.fields_for :item_images do |i|
= i.file_field :image, multiple: true, class: 'image-upload-dropfile-hidden', id:"image-label",type: 'file', name: "item_images[image][]"
1つのアップローダーで複数の画像を選択する為には、multiple: trueを記述する必要があります。
multiple: trueを記述した際、params内は配列として渡されるので、コントローラー側で配列の中身を取り出す処理が必要になります。
##ストロングパラメーター
private
def item_params
params.require(:item).permit(item_images_attributes: [:id, :item_id, :image])
end
今回コードが冗長になる為、itemsテーブルの他のキーのpermitの記述は抜いています。
ここで登場です、item_images_attributesメソッド。
item_images_attributesをpermitに加えると、コントローラで入れ子のitem_imagesの属性を@item.item_imagesとして扱えるようになります。
配列内にはitem_imagesテーブルのキーを記載しています。
##Formに入力したデータの保存
def create
if @item.save
params[:item_images]['image'].each do |img|
@item_image = @item.item_images.create(:image => img, :item_id => @item.id)
end
redirect_to item_path(@item.id)
end
end
念押しです。先ほどの@item_imageはcreateアクションで保存の処理を行うために、newアクションでインスタンス生成しました。
multiple: trueで複数の画像を渡しているので、params[:item_images]['image']の中身は配列であり、each文で一つ一つの要素に@item_image取り出す処理を行います。
これでDBにItemモデルと紐づいた画像が登録されます。