Programming Journal

学習したことの整理用です。

【Rails】Active Storageを使って画像を複数枚アップロード&削除する

実装したいこと

以前、ActiveStorageを使って画像をアップロードする機能を実装しました。
今回は、画像を複数枚アップロード&削除機能を実装したいです。
参照する記事が少なく手こずってしまいました。。特に削除機能は、情報が少なくて苦労しました。

study-diary.hatenadiary.jp

複数枚の画像を一度にアップロードする

Model, Controller and Viewを設定していきます。

Model

複数枚の画像をアップロードしたいモデルにhas_many_attachedを追加します。

class Post < ApplicationRecord
  belongs_to :user
  has_one_attached :image
  has_many_attached :main_images #追加
(略)
end

Controller

main_images: []これで配列を渡しています。末尾に追加します。

(略) 
 private

def post_params
    params.require(:post).permit(:title, :body, :image, main_images: []) #最後追加
end

View

複数枚の画像が配列に入っているので、eachで回して表示します。

#入力フォーム部分(gem 'simple_form'使用)
= f.input :main_images, as: :file, hint: 'JPEG/PNG (1200x400)', input_html: { multiple: true }

#画像表示部分
- if @post.main_images.attached?
        - @post.main_images.each do |image|
          = image_tag image.variant(resize: '300x100').processed
躓いたところ

gem 'simple_form'を使っているときは、複数枚選択を設定するとき、input_html: { multiple: true }を使います。
multiple: trueだけだと、機能しません。

ruby on rails 4 - Using simple_forms simple_field_for with a multipart file uploader for Carrierwave - Stack Overflow

アップロードした画像を削除するには

これが悩んでしまいました。。この記事を参考にして、新しくアクションを作って…と実装しようとしたのですが、うまくルーティングが組めず撃沈しました。
新しく画像削除用のコントローラーを生成してシンプルに実装したらようやくうまくできました。

file upload - Rails 5.2 Active Storage purging/deleting attachments - Stack Overflow

Controller

class Post::AttachmentsController < ApplicationController

  def destroy
    image = ActiveStorage::Attachment.find(params[:id])
    image.purge
    redirect_to posts_path
  end
end

ちなみに、継承元を含めるコントローラーを生成するコマンド❯ rails g controller post::attachments

Rooting

(略)
    resource :post do
      member do
        resources :attachments, only: %i[destroy], controller: 'post/attachments'
      end
    end

View

      - if @post.main_images.attached?
        - @post.main_images.each do |image|
          = image_tag image.variant(resize: '300x100').processed
          = link_to '削除', post_attachment_path(image.id), method: :delete, class: 'btn btn-danger' #追加