我通常使用滑轨和回形针保存图像。
带有附件的记录被销毁时,附件也会从文件系统中删除。
99%的时间这是正确的操作,但是即使删除了db记录,在某些情况下我也需要将附件保留在系统中。
我想知道是否有人知道该怎么做。
我尝试过通过销毁记录之前通过update_attribute将附件字段设置为nil,但是update_attribute也会删除该文件。
一种方法是忽略所有回调,但是需要其他一些回调,这似乎有点过多。任何人都知道更好的方法...
干杯。
您可能想看看回形针中如何实现Attachment#assign
(当您执行object.attachment = new_attachment
时会调用)。基本上,它会进行一些设置,然后调用Attachment#clear
,然后保存新文件。
Attachment#clear将旧文件放入删除队列中,当您再次调用save时,该文件将被处理,您想要的只是避免调用被清除,您可以通过编写新的assign方法跳过该行或通过猴子修补#clear
使其变为无操作状态。从理论上讲,您可以将猴子修补在您希望发生这种情况的实例上,但是在我看来,您可能希望对整个项目都这样做。
或者您可以清除保存处理队列的实例变量。该变量没有访问器,但是执行instance_variable_get
仅保留回形针生成的数据库字段(文件名,内容类型,文件大小)不会保留该文件。 destroy方法仍将通过索引指向它。
在销毁记录之前,请尝试将ID更改为某个随机数(例如999898)。如果抛出异常,则也将字段设为nil。这样,记录将不再指向文件,并在记录被销毁时保留。
所以问题是怎么回事?您正在尝试实施撤消,以便有人可以删除然后取消删除吗?
我认为您的解决方案应处理“清除”标志,然后在清除标志为true的情况下每晚删除批处理作业。只要所有获取都用于带有索引的clear = false的记录,就不会影响性能。这个问题在解决方案中只是带有“错误”的感觉。只是提供了不同的视角。
也许有点偏离主题:
[如果附件存储在S3上,则您可以覆盖has_attached_file
方法,并且仅传递附件名称,而无需任何选项。在这种情况下,回形针会认为文件存储在文件系统中,只会删除任何内容。同样也没有例外。
我知道此解决方案可能有点笨拙/难看,但简单且可行。
对我来说,覆盖Paperclip::Attachment#clear
方法并不能解决问题。我必须重写Paperclip::Attachment#queue_all_for_delete
。
[正如Alex Falke所说,Paperclip具有:preserve_files
选项,因此很显然,如果您想保留所有附件,可以使用它而不是覆盖它。
如果有特殊情况,改写#queue_all_for_delete
是可行的方法,但是您必须有选择地这样做。猴子修补程序是全球性的,因此它不是最佳方法。我试图使用改进来限制猴子补丁的范围,但是词汇范围在我的用例中不能很好地发挥作用。
所以我最终得到了这个模块,该模块将自身注入方法查找路径,并有选择地为#queue_all_for_delete
定义或取消定义无操作覆盖:
module PaperclipKeepAttachment
def self.with_patch
patch
add_override
yield
ensure
remove_override
end
def self.patch
me = self
Paperclip::Attachment.class_eval{ prepend me } unless Paperclip::Attachment.ancestors.include?(me)
end
def self.add_override
define_method(:queue_all_for_delete) do
# no-op
end
end
def self.remove_override
remove_method(:queue_all_for_delete)
end
end
使用它,您可以执行以下操作:
PaperclipKeepAttachment.with_patch do
# The record will be destroyed but the attachment kept intact
first_record.destroy
end
# The record will be destroyed and the attachment removed
second_record.destroy
gem允许您进行软删除:
(来自paperclip)
一个选项可用于保留附件,以便在软删除的模型中正常播放。 (acts_as_paranoid,偏执狂等)
has_attached_file :some_attachment, {
preserve_files: true,
}
这将防止在销毁模型时清除some_attachment,因此在以后恢复对象时它仍然存在。