首先,假设您在 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 复选框时,它会从用户实例中加载默认值 "0"。如果勾选了该字段,则控制器将将图像删除更新为 "1",并在保存用户时检查是否要删除图像。
has_attached_file :asset
=>
attr_accessor :delete_asset
before_validation { asset.clear if delete_asset == '1' }
form.check_box(:delete_asset)
就足够了。has_attached_file :asset
has_destroyable_file :asset
我创建了一个初始化程序,可以添加到 config/initializers/
目录下。https://gist.github.com/3954054 - Sunny这是Benoit的答案,但包装在一个模块中,并覆盖了嵌套属性模型的边缘情况,其中销毁复选框是模型上唯一更改的内容。
它将适用于模型上的所有附件。
# 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
attachment_definitions
简直救了我的命。 - t56kattr_accessible :"delete_#{name}"
。 - t56khas_attached_file
语句下方添加一行include DeletableAttachment
即可。 - Paul Odeon:delete_<your_attribute>
。 - ivanxuu记得将这个添加到你的页面模型中:
attr_accessible :image_delete
修改了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
通过在模型端实现delete_attachment
,可以用更少的代码实现此操作。
class MyModel < ApplicationRecord
has_attached_file :image
def image_delete=(other)
self.image = nil if other == "1" or other == true
end
end
destroy_image?
方法中更改条件为self.image.clear if @image_delete == "1" and !image.dirty?
来解决这个问题。 - Zeeshan@page.image.destroy
只会删除云端的附件。因此,你需要明确保存你的模型记录@page.save
。否则,你的记录仍然会被认为有一个附加的图像/文件,但生成的链接将指向错误。(Rails 4.1 / Paperclip 4.2.0 / Amazon S3) - Sylvain FARNAULT