I'm using rails and paperclip to save images, the usual way.
When a record with an attachment is destroyed, the attachment also gets deleted from the file system.
99% of the time this is the correct action, however there is a case where I need the attachment to remain in the system even though the db record is deleted.
I was wondering if anyone knew how to do this.
I've tried setting the attachment fields to nil via an update_attribute before destroying the record, but the update_attribute also delete the file.
One way would be to ignore all the callbacks, however some of the other call backs are needed and this seems a little too much. Anyone know any better ways...
Cheers.
you may want to take a look at how Attachment#assign
(called when you do object.attachment = new_attachment
) is implemented in paperclip.
Basically, it makes a bit of setup, then calls Attachment#clear
, then it saves the new file.
Attachment#clear puts the old file in a deletion queue that is processed when you call save again, what you want is simply to avoid the call to clear, which you could do by either writing a new assign method which skips that line or by monkey patching #clear
so that it becomes a no-op. In theory you could just monkey patch it on the instances where you want this to happen, but it seems to me you may want to do it for the whole project.
Or you can clear the instance variable holding the processing queue. That variable does not have an accessor, but it should be trivial to do an instance_variable_get
The gem allows you to do a soft delete:
(from paperclip)
An option is available to preserve attachments in order to play nicely with soft-deleted models. (acts_as_paranoid, paranoia, etc.)
has_attached_file :some_attachment, {
preserve_files: true,
}
This will prevent some_attachment from being wiped out when the model gets destroyed, so it will still exist when the object is restored later.
Nil-ling the database fields that paperclip generates (file_name, content_type, file_size) would not keep the file. The destroy method will still point it through the index.
Try changing the id to some random number (e.g. 999898) before you destroy the record. If it throws exception, also nil the fields. That way the record will no longer points at the file and will remain as the record gets destroyed.
So the question is what is going on? You are trying to implement undo so someone can delete and then undelete?
I would argue that your solution should be dealing with a "clear" flag and then deleting in a batch job nightly if the clear flag is true. Would not impact performance as long as all gets are for records where clear = false with an index. The question just has a feel of "wrongness" in the solution to it. Just offering a different perspective.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With