Home > database >  Rails Active Storage - Keep Existing Files / Uploads?
Rails Active Storage - Keep Existing Files / Uploads?

Time:04-29

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?

CodePudding user response:

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 with config.active_storage.replace_on_assign_to_many set to true before upgrading. To append new attachables to the Active Storage association, prefer using attach. 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.

  • Related