I have a Rails model with:
has_many_attached :files
When uploading via Active Storage by default if you upload new files it deletes all the existing uploads and replaces them with the new ones.
I have a controller hack from this which is less than desirable for many reasons:
What is the correct way to update images with has_many_attached in Rails 6
Is there a way to configure Active Storage to keep the existing ones?
Looks like there is a configuration that does exactly that
config.active_storage.replace_on_assign_to_many = false
Unfortunately it is deprecated according to current rails source code and it will be removed in Rails 7.1
config.active_storage.replace_on_assign_to_many
is deprecated and will be removed in Rails 7.1. Make sure that your code works well withconfig.active_storage.replace_on_assign_to_many
set totrue
before upgrading. To append new attachables to the Active Storage association, prefer usingattach
. Using association setter would result in purging the existing attached attachments and replacing them with new ones.
It looks like explicite usage of attach
will be the only way forward.
So one way is to set everything in the controller:
def update
...
if model.update(model_params)
model.files.attach(params[:model][:files]) if params.dig(:model, :files).present?
else
...
end
end
If you don't like to have this code in controller. You can for example override default setter for the model eg like this:
class Model < ApplicationModel
has_many_attached :files
def files=(attachables)
files.attach(attachables)
end
end
Not sure if I'd suggest this solution. I'd prefer to add new method just for appending files:
class Model < ApplicationModel
has_many_attached :files
def append_files=(attachables)
files.attach(attachables)
end
end
and in your form use
<%= f.file_field :append_files %>
It might need also a reader in the model and probably a better name, but it should demonstrate the concept.