Rails Paperclip如何删除附件?

时间:2010-12-14 04:19:07

标签: ruby-on-rails ruby paperclip

我在Rails 3上使用Paperclip(带有Amazon s3)。我想使用更新操作删除现有附件而不替换它

我只找到了这个here的一个例子,并且无法使其工作,它只是不会删除,日志中没有任何内容可以说明原因。我想在表格上做这样的事情:

<%- unless @page.new_record? || !@page.image? -%>
    <%= f.check_box :image_delete, :label => 'Delete Image' %>
<%- end -%>

(页面是模型的名称,image是保存附件的属性名称)

但是如何检测该复选框,更重要的是,如何删除图像?我感谢任何帮助!

6 个答案:

答案 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