0

What I'd like to know is very simple:
How to retain uploaded files on form resubmission in Rails6 with ActiveStorage?

I have checked the below as a similar question.
When using activestorage in Rails 6, how do I retain a file when redisplaying a form?

The summary of suggested solution in it is like this:

Active Storage store attachments after the record is saved rather than immediately. So, if you want to persist assigned file after validation error, you must upload and save the file.

For example,

def update
  ...
  # `obj` is your model that using `has_one_attached`.
  if(obj.update)
    redirect_to ...
  else
    obj.attachment_changes.each do |_, change|
      if change.is_a?(ActiveStorage::Attached::Changes::CreateOne)
        change.upload
        change.blob.save
      end
    end
    ...
  end
end

https://medium.com/@TETRA2000/active-storage-how-to-retain-uploaded-files-on-form-resubmission-91b57be78d53

or, use direct_upload:

= f.file_field :doc, direct_upload: true
= f.hidden_field :doc, value: f.object.doc.signed_id if f.object.doc.attached?

By using these solutions, yeah, I managed to retain a file when redisplaying a form. However, these are against this pr intention. pr says

It’s of little use to identify an invalid file after it’s already been shipped off to storage:

you might use a size validation to limit the cost that a single file can add to your AWS bill, but if the file is stored before validations run, you incur its cost regardless.

So, I don't want to upload file to persist it after validation.
How can I retain the file without uploading file and saving blob? I cannot use CarrierWave.

user16012143
  • 139
  • 7
  • When you upload a file the "normal" way with a multipart form you will get a `ActionDispatch::Http::UploadedFile` in the parameters. This is basically just a tempfile so if you want to persist it from one request to the next you need to copy its contents to a permanent file. The path to the permanent file must then be passed to the next request via something like a hidden input or the session. This isn't something Rails will do for you but its pretty easy to do if you get your head around the fundamentals. https://guides.rubyonrails.org/form_helpers.html#uploading-files – max Mar 24 '22 at 14:55
  • What `direct_upload: true` does is quite different and it may not be relevant to you. It uses ActiveSupports snazzy little Ajax handler to send a POST request to create a blob with the file. This request returns an ID to the blob which is then used to update the blob with the id and type of whatever record you are creating. If you don't "claim" the attachment it ends up orphaned. – max Mar 24 '22 at 15:02
  • Thank you for your answer! `its pretty easy to do if you get your head around the fundamentals.` This means that ActiveStorage with Rails6 does not provide a simple way to do this, right? – user16012143 Mar 24 '22 at 15:13
  • Oh, sorry. I'm not familiar to `direct_upload`. Anyway, many blog posts say We have to use `signed_id` to retain upload files, but we have to upload files and save blob record to use it. I'm in trouble with it... – user16012143 Mar 24 '22 at 15:16
  • 1
    No, what this actually means is that what you think is simple is actually more complex. Even if you do persist the file you still have to handle cleaning up afterwards.... You're not really solving anything by not creating an activesupport attachment. – max Mar 24 '22 at 15:17
  • 1
    You can't just take a file which is a chunk of binary and stuff it into the `value` attribute on a form when re-rendering the form. – max Mar 24 '22 at 15:20
  • I really appreciate your help. OK, I cannot do stuff `ActionDispatch::Http::UploadedFile#tempfile` IO into attributes... If so, is uploading files and saving ActiveStorage::Blob the best way to retain files? How to clean up unused file automatically? – user16012143 Mar 24 '22 at 15:31

0 Answers0