How do you use ActiveStorage has_many_attached i active admin when editing images on a model?

Viewed 3268

I am using Active admin for editing all models in my app, and have previously used paperclip. In this app I am using Active Storage on and Activity model with the following:

has_many_attached :images

I have found this way of being able to upload multiple images

form do |f|
  columns do
    column do
      f.inputs do
        [removed stuff here]
        f.input :images, as: :file, input_html: { multiple: true }
      end
    f.submit
    end
  end
end

But I really want to be able to view, change or delete individual images in the form with individual input fields for each image and in the end of the list a field to add another image. How do I do that? Is it even doable?

2 Answers

possibly you can do something like,

ParentModel
 has_many:child_models
 accepts_nested_attributes_for :child_models, :allow_destroy => true

ChildModel
 Belongs_to :parent_model
 has_one_attched :image

form do |f|
  columns do
    column do
      f.inputs do
        f.inputs "images" do
         f.has_many :child_models  do |cm|
         cm.input :image, label: "Add picture",  :as => :file
        end  
      end
      end
    f.submit
    end
  end
end

Although the approach by roshiend was downvoted, I think that it would work fine for me, so I tried it out. The following code works, but only on creating new attachment blobs. It fails to work correctly when updating, although there are workarounds.

This seems to uncover a bug in AA for (in my case) nested polymorphic resources so I am reaching out to see if I am doing anything wrong before I file an issue with AA. Can anyone see if I went wrong somewhere?

Bug Summary

In nested forms, polymorphic image attachment does not upload a new file (when replacing an existing one), nor can it be displayed as an image hint, when using ActiveStorage as the file uploader.

Expected behavior

When editing a resource with an attached image blob, I expect (1) to be able to display a small thumbnail using "hint:" and I expect when choosing a new file that the old file is overwritten. I expect (2) the same behavior when this resource is nested into another resource, and the form with f.has_many is implemented.

Actual behavior

Expectation (1) works fine. But implementing (2) I find that the old file is not overwritten with the new file (returns Completed 304 Not Modified). Furthermore if I try to show a thumbnail in the sub-form using "hint:" I get an exception

Can't resolve image into URL: to_model delegated to attachment, but attachment is nil

The problem it seems is inside the has_many the .image method loses touch with the attachment object.

How to reproduce

Given a model and a polymorphic attachments model:

class PayloadKind < ApplicationRecord
  has_many :attachments, as: :attachable
  accepts_nested_attributes_for :attachments, allow_destroy: true
end

class Attachment < ApplicationRecord
  belongs_to :attachable, polymorphic: true
  has_one_attached :image
end

First, look at the form for Attachment:

ActiveAdmin.register Attachment do
  permit_params :name, :image
  form do |f|
    f.inputs "attachment" do
      f.input :name
      f.input :image, as: :file, hint: image_tag(f.object.image.variant(resize_to_limit: [100,100])) # hint: works fine
    end
    f.actions  # uploads a new file if the user wants a change
  end

When I view the form, the image hint shows up fine. When I execute the update using the above form, with a new file specified to replace the old one, the log shows expected behavior

ActiveStorage::Blob Load (0.2ms)  SELECT "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = $1 LIMIT $2  [["id", 52], ["LIMIT", 1]]
  Disk Storage (0.1ms) Checked if file exists at key: variants/vw057sxlchfi6omkig359sa893hs/6fc72cc8335bf38f78ee581ac0cfbf2ff591b7f70c9c06b30882cae6844770c8 (no)
  Disk Storage (0.7ms) Downloaded file from key: vw057sxlchfi6omkig359sa893hs
  Disk Storage (0.4ms) Uploaded file to key: variants/vw057sxlchfi6omkig359sa893hs/6fc72cc8335bf38f78ee581ac0cfbf2ff591b7f70c9c06b30882cae6844770c8

Now edit the same Attachment instance, but nested in the form for PayloadKind

ActiveAdmin.register PayloadKind do
  permit_params :id, :name, :variety, :description, attachments_attributes: [:name, :image, :id, :attachable_id, :attachable_type, :_destroy]
  form do |f|
    f.semantic_errors
    f.inputs "parameters" do
      f.input :name
      f.input :variety
      f.input :description
      f.object.attachments.each do |at|
        span image_tag(at.image.variant(resize_to_limit: [100,100]))  # This works fine
      end
      f.has_many :attachments, allow_destroy: true do |at|
        at.input :name
        at.input :image, as: :file, hint: image_tag(at.object.image)  # The hint: bombs.
      end
    end
    f.actions
  end

I do not see the ActiveStorage activity in the logs, just ends in Completed 304

But I have no issue creating a new image attachments, images upload fine.

===

Workaround

The workaround to the image hint not showing is to use image_tag outside of the f.has_many block, which works if not as attractive as I would like.

The workaround to the new image not uploading is to delete the nested object first and then add a new one.

Related