我在Rails 3上使用Paperclip(带有Amazon s3)。我想使用更新操作删除现有附件而不替换它。
我只找到了这个here的一个例子,并且无法使其工作,它只是不会删除,日志中没有任何内容可以说明原因。我想在表格上做这样的事情:
<%- unless @page.new_record? || !@page.image? -%>
<%= f.check_box :image_delete, :label => 'Delete Image' %>
<%- end -%>
(页面是模型的名称,image是保存附件的属性名称)
但是如何检测该复选框,更重要的是,如何删除图像?我感谢任何帮助!
答案 0 :(得分:99)
首先,当你在form_for中创建一个check_box时(它看起来像你),那么默认情况下表单应该发送:image_delete如果选中则为“1”,如果未选中则返回“0”。方法声明如下所示:
def check_box(method, options = {}, checked_value = "1", unchecked_value = "0")
这表明您可以根据需要指定其他值,但这当然是可选的。
其次,手动删除附件而不删除附加到的模型实例的调用是:
@page.image.destroy #Will remove the attachment and save the model
@page.image.clear #Will queue the attachment to be deleted
要完成通过复选框删除图像的方式,可能会在页面模型中添加以下内容:
class Page < ActiveRecord::Base
has_attached_file :image
before_save :destroy_image?
def image_delete
@image_delete ||= "0"
end
def image_delete=(value)
@image_delete = value
end
private
def destroy_image?
self.image.clear if @image_delete == "1"
end
end
这样,当您创建表单并添加:image_delete复选框时,它将从User实例加载默认值“0”。如果检查该字段,则控制器会将image_delete更新为“1”,当用户保存时,它将检查是否要删除图像。
答案 1 :(得分:95)
has_attached_file :asset
=&GT;
attr_accessor :delete_asset
before_validation { asset.clear if delete_asset == '1' }
无需破坏资产,Paperclip会这样做。
form.check_box(:delete_asset)
形式就足够了。
答案 2 :(得分:12)
这是Benoit的答案,但是包含在一个模块中,并且覆盖了嵌套属性模型的边缘情况,其中destroy tickbox是模型上唯一改变的东西。
它将适用于模型上的所有附件。
# This needs to be included after all has_attached_file statements in a class
module DeletableAttachment
extend ActiveSupport::Concern
included do
attachment_definitions.keys.each do |name|
attr_accessor :"delete_#{name}"
before_validation { send(name).clear if send("delete_#{name}") == '1' }
define_method :"delete_#{name}=" do |value|
instance_variable_set :"@delete_#{name}", value
send("#{name}_file_name_will_change!")
end
end
end
end
答案 3 :(得分:5)
请记住将此添加到您的Page模型中:
attr_accessible :image_delete
答案 4 :(得分:0)
Paul的解决方案的修改版本,支持Rails 5自定义属性。我只是希望有一种方法可以在has_attached_file
定义之前将模块包含在文件的顶部。
module Mixins
module PaperclipRemover
extend ActiveSupport::Concern
included do
attachment_definitions.keys.each do |name|
attribute :"remove_#{name}", :boolean
before_validation do
self.send("#{name}=", nil) if send("remove_#{name}?")
end
end
end
end
end
答案 5 :(得分:0)
仅通过在模型侧实现delete_attachment
就能用更少的代码实现这一目标。
class MyModel < ApplicationRecord
has_attached_file :image
def image_delete=(other)
self.image = nil if other == "1" or other == true
end
end