2
5

More than 3 years have passed since last update.

[Rails]ItemImagesテーブルとItemsテーブルを別けた際のテーブルの紐付けから複数画像アップロードまで

Last updated at Posted at 2020-03-07

Gemのインストール

Gemfile
gem 'carrierwave'
gem 'rmagick'

画像投稿機能に関わるgemのインストールをお忘れなく。
gem'rmagick'は画像のリサイズなどに使用します。

前置き

terminal
rails g uploader images

リサイズなど画像の設定をする為のファイルが生成されます。

app/uploaders/images_uploader.rb

モデルとの紐付け

imageが存在するモデルをItem_Imageモデルとしています。

ItemImagesテーブルとItemsテーブルは1対多の関係にあります。
画像は沢山のItemを持っているからです。
2020-03-07 23.14のイメージ.jpeg

item.rb
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モデルに追加されました。
後ほど使用します。

item_image.rb
class ItemImage < ApplicationRecord
    belongs_to :item 

    mount_uploader :image, ImageUploader
end

ItemImagesテーブルに追加したカラムの名前をmount_uploaderに指定します。

Itemsコントローラーの設定

items_controller.rb
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の作成

new.html.haml
= 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内は配列として渡されるので、コントローラー側で配列の中身を取り出す処理が必要になります。

ストロングパラメーター

items_controller.rb
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に入力したデータの保存

items_controller.rb
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モデルと紐づいた画像が登録されます。

2
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
5