Project based on RoR 5.2. For attachments uploading I use Carrierwave gem and AWS S3 bucket as storage.
I need to implement versioning for uploaded files with same names.
I mean that file with the same name should not be replaced when I will upload a new one. For example: model User has a mounted uploader for documents. If I will upload file with name «doc.docx» and after I will upload one else file for the same model object and with the same name, old file will be replaced with new one.
I have already investigated that I can generate token or add timestamp to get unique filename, but I need that if I will upload the new file with same name (for example 'doc.docx') for the same object, it shoild be renamed to 'doc(1).docx' or 'doc_1.docx'. And the new one will be renamed to 'doc(2).docx' or 'doc_2.docx', etc.
Versioning in the AWS panel for this bucket has already enabled.
Is there any way to achieve this? I'm ready to change from Carrierwave to Active Storage. But I have not found at least one case for this.
Any suggestions? Thanks in advance!
I have some ideas about renaming. At first, we can split your problem:
I solved my problem with renaming with similar code (Carrierwave + video processing). Here I created thumbnail version for an uploaded video, with a specific name (write your custom function instead of png_name
, you can check a number of previously uploaded files and etc):
# Create different versions of your uploaded files:
# ffmpegthumbnailer
version :thumb do
process thumbnail: [{ format: 'png', size: 360, logger: Rails.logger }]
def full_filename for_file
png_name for_file, version_name
end
end
version :preview do
process thumbnail: [{ format: 'png', size: 600, logger: Rails.logger }]
def full_filename for_file
png_name for_file, version_name
end
end
def png_name(for_file, version_name)
%Q{#{version_name}_#{for_file.chomp(File.extname(for_file))}.png}
end
And you can solve the problem with versioning by creating proxy-model. For instance, you have User
model, than you create an association called Document
. You can mount your uploader to the Document model, and use code above for the renaming.
class User < ApplicationRecord
has_many :documents, dependent: :destroy
def last_document
documents.last
end
end
class Document < ApplicationRecord
mount_uploader :file, DocumentUploader
validates_integrity_of :file
end