web-dev-qa-db-fra.com

Rails Paperclip comment supprimer la pièce jointe?

J'utilise Paperclip (avec Amazon s3) sur Rails 3. Je veux supprimer une pièce jointe existante sans la remplacer en utilisant une action de mise à jour.

Je n'ai trouvé qu'un exemple de cela ici et je n'ai pas pu faire fonctionner cela, il ne voulait tout simplement pas supprimer et il n'y avait rien dans les journaux pour dire pourquoi. Je voulais faire quelque chose comme ça sur le formulaire:

<%- unless @page.new_record? || [email protected]? -%>
    <%= f.check_box :image_delete, :label => 'Delete Image' %>
<%- end -%>

(la page est le nom du modèle, l'image est le nom de l'attribut qui contient la pièce jointe)

Mais comment puis-je détecter cette case à cocher et, plus important encore, comment supprimer l'image? J'apprécie toute aide!

83
jyoseph

Tout d'abord, lorsque vous créez une case à cocher dans un form_for (qui vous ressemble), le formulaire doit par défaut envoyer: image_delete comme "1" si coché et "0" si non coché. La déclaration de méthode ressemble à ceci:

def check_box(method, options = {}, checked_value = "1", unchecked_value = "0")

Ce qui montre que vous pouvez attribuer d'autres valeurs si vous le souhaitez, mais cela est bien sûr facultatif.

Deuxièmement, l'appel pour supprimer manuellement une pièce jointe sans supprimer l'instance de modèle à laquelle elle est attachée est:

@page.image.destroy #Will remove the attachment and save the model
@page.image.clear #Will queue the attachment to be deleted

Et pour accomplir votre façon de supprimer les images via une case à cocher, ajoutez peut-être quelque chose comme ceci à votre modèle de page:

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

De cette façon, lorsque vous créez votre formulaire et ajoutez la case à cocher: image_delete, il chargera la valeur par défaut "0" à partir de l'instance de l'utilisateur. Et si ce champ est coché, le contrôleur mettra à jour l'image_delete à "1" et lorsque l'utilisateur sera enregistré, il vérifiera si l'image doit être supprimée.

100
DanneManne

has_attached_file :asset

=>

    attr_accessor :delete_asset
    before_validation { asset.clear if delete_asset == '1' }

Pas besoin de détruire les actifs, Paperclip le fera.

Sous la forme form.check_box(:delete_asset) suffira.

95
Benoit B.

C'est la réponse de Benoit, mais enveloppé dans un module, et couvrant le cas Edge des modèles d'attributs imbriqués où la case à cocher détruire est la seule chose qui a changé sur le modèle.

Il s'appliquera à toutes les pièces jointes du modèle.

# 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
12
Paul Odeon

n'oubliez pas d'ajouter cela à votre modèle de page également:

attr_accessible :image_delete
5
Glenn McW

Version modifiée de la solution de Paul, pour prendre en charge Rails 5 attributs personnalisés. Je souhaite juste qu'il y ait un moyen d'inclure le module en haut du fichier, avant has_attached_file définitions.

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
0
JBlake