How to edit multiple attached images using ActiveStorage `has_many_attached` in ActiveAdmin

Viewed 4474

I have a simple model that can have multiple images attached via ActiveStorage handling the file storage.

I am using ActiveAdmin to edit my model and to upload/attach the images - so far no problems.

The problem is, when I want to edit my model, and add new images, then the previous ones are deleted, and only the new ones added.

I can do a preview of already attached images, and could also delete them separately, but how do I achieve, that by uploading new images, the old ones are NOT deleted?

My model:

class Post < ActiveRecord::Base
  has_many_attached :images
end

My ActiveAdmin page:

ActiveAdmin.register AdminPost do
  permit_params images:[]

  form do |f|
    f.input :images, as: :file, input_html: { multiple: true }

    if @resource.images.exists?
      @resource.images.map do |m|
        para image_tag m
      end
    end
  end 
end
2 Answers

Assuming you are using rails 6.0+; you can solve this by adding following code in to your environments (i.e - development.rb ) https://github.com/rails/rails/issues/35817#issuecomment-628654948

config.active_storage.replace_on_assign_to_many = false

in your form,

form do |f|
 f.input :images, as: :file, input_html: { multiple: true }
 f.object.images.each do |image|
  span image_tag(image)
 end
end 

So I chose the way of adding the new attachments manually, so they don't replace the existing attached images. I added a field to handle the posted images, and a method to add them in my model.

class Post < ActiveRecord::Base
  has_many_attached :images

  attr_accessor :new_images

  def attach_images
    return if new_images.blank?

    images.attach(new_images)
    self.new_images = []
  end
end

And the ActiveAdmin page controller handles the upload, and calls the new method:

ActiveAdmin.register AdminPost do
  permit_params new_images:[]

  form do |f|
    f.input :new_images, as: :file, input_html: { multiple: true }

    if @resource.images.exists?
      @resource.images.map do |m|
        para image_tag m
      end
    end
  end 

  controller do
    after_save :add_images

    def add_images(post)
      post.attach_images
    end
  end
end
Related