Rails Paperclip 첨부 파일을 삭제하는 방법?


84

내가 사용하고 종이 클립을 레일 3. 내가 기존 첨부 파일을 삭제하려면 (/ 아마존 S3 W) 를 교체하지 않고 업데이트 작업을 사용.

여기 에서 한 가지 예만 찾았고 작동하지 못했습니다. 삭제되지 않았고 로그에 이유를 말할 수있는 내용이 없었습니다. 나는 다음과 같은 양식을 작성하고 싶었습니다.

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

(페이지는 모델 이름, 이미지는 첨부 파일이있는 속성 이름)

그러나이 확인란을 어떻게 감지하고 더 중요한 것은 이미지를 어떻게 삭제합니까? 도와 주셔서 감사합니다!

답변:


104

먼저 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"로 업데이트하고 사용자가 저장 될 때 이미지를 삭제할 것인지 확인합니다.


이 예에서 Page # image has_attached_file는 image라는 이름의 첨부 파일이있는 다른 모델을 참조 합니까?
John Bachir 2011 년

@page는 has_attached_file : image라는 모델 변수이지만 어떤 이유로 모델 사용자 이름을 지정한 것 같습니다. 명확하게 변경하고 업데이트하겠습니다.
DanneManne 2011 년

좋아요, 더 이해가
갑니다

왜 self.image.destroy를 수행하지 않는지 이해할 수 없습니다. 기본 파일을 지우고 페이지 모델의 이미지에 대한 메타 정보를 유지합니까? 왜 이렇게 하시겠습니까? (그리고 질문 아스 커는 어떻게 원하는 것을 그의 아닌 것 같아)
존 Bachir

11
이 접근 방식도 저에게 효과적이었습니다 ...하지만 한 가지 문제에 직면했습니다 ... 사용자가 image_delete 확인란을 선택하고 양식에 동시에 새 이미지를 추가하면 이전 이미지가 삭제되고 새 이미지가 저장되지 않습니다 . 조건을 self.image.clear if @image_delete == "1" and !image.dirty?in destroy_image?method 로 변경하여이 문제를 해결했습니다.
Zeeshan 2011-08-15

97

has_attached_file :asset

=>

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

자산을 파괴 할 필요가 없습니다. Paperclip이 해드립니다.

양식으로 form.check_box(:delete_asset)충분합니다.


3
이것은 작동하며 @DanneManne 대답 IMHO보다 간단합니다. 아주 좋아요! :)
MetalElf0

이것에 대한 사양을 어떻게 작성 하시겠습니까?
Hengjie

1
감사 ! 좀 더 슬림하게하기 has_attached_file :asset has_destroyable_file :asset 위해 config/initializers/ gist.github.com/3954054
Sunny

2
적어도 accepts_nested_attributes를 통해이 방법에 문제가 있음을 발견했습니다. 다른 속성이 변경되지 않은 경우 before_validation은 중첩 된 저장에서 트리거되지 않습니다. 솔루션에 대한 내 대답은 아래를 참조하십시오
폴 오데

4
난 당신이 매개 변수를 허용 할 필요가 생각 @SurgePedroza : delete_asset를 참조 guides.rubyonrails.org/...
sman591

12

이것은 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

1
이것이 더 많은 관심을받지 못한 이유를 모릅니다. attachment_definitions내 생명을 구했습니다.
okay56k 2014-06-10

그래도이 라인이 필요합니다 :attr_accessible :"delete_#{name}"
okay56k 2014-06-10

2
위의 예는 관심사 또는 모델 폴더에 있어야합니다. 당신이 그냥 줄을 추가 할 모델에서 include DeletableAttachment어떤 아래 has_attached_file
폴 오데

2
rails3에서는 attr_accessible이 필요합니다. : "delete _ # {name}"또한
Mateu

1
:delete_<your_attribute>컨트롤러에서 강력한 매개 변수를 사용 하는 경우 허용 하는 것을 잊지
마십시오

5

이것을 페이지 모델에도 추가하는 것을 잊지 마십시오.

attr_accessible :image_delete

1

Rails 5 사용자 정의 속성을 지원하도록 Paul 솔루션의 수정 된 버전. 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

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.