Brief Description
We have cases in code where we dup the existing record and then will update the some of the attributes on duped record. Unfortunately when shrine file is changed in the duped record, then original record's image is deleted from the store.
In our case, we also want to make new copy from existing files, that where not changed. So if a record is deleted, the images of all other records as still present. Previously we used :copy plugin what was removed.
Expected behavior
I expect the original record file to still be present after I have changed the file in duped record.
Actual behavior
When changing the file in duped record, then original record file is deleted.
Simplest self-contained example code to demonstrate issue
require "active_record"
require "shrine"
require "shrine/storage/memory"
require "sqlite3"
require "down"
Shrine.storages = {
cache: Shrine::Storage::Memory.new,
store: Shrine::Storage::Memory.new,
}
Shrine.plugin :activerecord
class DocumentUploader < Shrine
plugin :determine_mime_type
end
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.connection.create_table(:documents) { |t| t.text :image_data }
class Document < ActiveRecord::Base
include DocumentUploader[:image]
end
document = Document.create(image: Down.download("https://picsum.photos/10"))
document2 = document.dup
document2.update!(image: Down.download("https://picsum.photos/10"))
puts document.image.exists? #=> false
puts document2.image.exists? #=> true
Current workaround
require "active_record"
require "shrine"
require "shrine/storage/memory"
require "sqlite3"
require "down"
Shrine.storages = {
cache: Shrine::Storage::Memory.new,
store: Shrine::Storage::Memory.new,
}
Shrine.plugin :activerecord
class DocumentUploader < Shrine
plugin :determine_mime_type
class Attacher < Shrine::Attacher
def duped!
@duped = dup if file
end
def duped?
@duped.present? || false
end
def copy_duped_file?
duped? && @duped.file == file
end
def changed?
super || copy_duped_file?
end
def save
# Copy the image when duped record is saved, but the image remained the same
attach(file, storage: file.storage_key) if copy_duped_file?
super
end
def destroy_previous
# Do not delete the previous file, when it was duped
return if duped? && @duped.file == @previous&.file
super
end
end
end
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.connection.create_table(:documents) { |t| t.text :image_data }
class Document < ActiveRecord::Base
include DocumentUploader[:image]
def initialize_dup(other)
super
image_attacher.duped!
end
end
document = Document.create(image: Down.download("https://picsum.photos/10"))
document2 = document.dup
document2.update!(image: Down.download("https://picsum.photos/10"))
puts document.image.exists? #=> true
puts document2.image.exists? #=> true
document3 = document.dup
puts document.image == document3.image #=> true
document3.save! # image is copied when duped record is saved
puts document.image == document3.image #=> false
System configuration
Ruby version: 3.0.4
Shrine version: 3.4.0
Brief Description
We have cases in code where we dup the existing record and then will update the some of the attributes on duped record. Unfortunately when shrine file is changed in the duped record, then original record's image is deleted from the store.
In our case, we also want to make new copy from existing files, that where not changed. So if a record is deleted, the images of all other records as still present. Previously we used
:copyplugin what was removed.Expected behavior
I expect the original record file to still be present after I have changed the file in duped record.
Actual behavior
When changing the file in duped record, then original record file is deleted.
Simplest self-contained example code to demonstrate issue
Current workaround
System configuration
Ruby version: 3.0.4
Shrine version: 3.4.0