2010-02-05 3 views
2

나는 attachment_fu를 사용하여 사용자로부터의 파일 업로드를 허용하는 첨부 파일을 가지고 있다고 가정 해 보겠습니다. 첨부 파일을 "딥 카피"(또는 루비 - ese, 딥 클론)하여 "db_files"테이블에 완전히 새로운 바이너리 오브젝트를 생성하고 싶습니다.레일스, Attachment_fu - 데이터베이스 스토리지 첨부 파일의 전체 복사본

아직 해결되지 않은 문제를 발견했습니다. 이 블로그 게시 : http://www.williambharding.com/blog/rails/rails-faster-clonecopy-of-attachment_fu-images/

파일 시스템 기반 저장 장치로 작동하는 것으로 추정되는 방법을 보여줍니다. db 기반 저장소의 경우 "전체 복사본"이 실패합니다. 새 "첨부 파일"이 만들어 지지만 기존 db_file_id를 사용하므로 얕은 복사본을 수행합니다. 내가 저장 방법을 참조 attachment_fu의 db_file_backend.rb 내부

: 나는 확신 할 수 있지만 그래서

 # Saves the data to the DbFile model 
     def save_to_storage 
     if save_attachment? 
      (db_file || build_db_file).data = temp_data 
      db_file.save! 
      self.class.update_all ['db_file_id = ?', self.db_file_id = db_file.id], ['id = ?', id] 
     end 
     true 
     end 

, 나는이를 해독하려고 나는 "build_db_file"생각 DbFile.new에 대한 몇 가지 루비 메타 프로그래밍 마법 속기이다 이 (소스를 grepping이 아무런 언급이 표시되지 않으며, 나는 Google에서 찾을 수 없습니다).

나는 그것이 무엇을하고 있는지 확실히 모르겠다. 그러나 나의 이론은 db_file이 "deep copy"시도 (링크 된 코드에서)의 일부로 소스 obj로부터 복사되고 있다는 것이므로 단순히 만들기 대신 저장하십시오.

def save_to_storage 
    if save_attachment? 
     if self.new_record? 
     db_file = DbFile.new :data => temp_data 
     self.class.update_all ['db_file_id = ?', self.db_file_id = db_file.id], ['id = ?', id] 
     end 
    end 
    true 
    end 

이 실제로 복제 된 개체하지만 불행히도 잘 동작 :

내 초기 이론은 부모 (첨부 파일) 객체가 깊은 복사 시도시에 "새"로 설정하여 내가 좋아하는 뭔가를 한 것이었다 일반적이고 복제되지 않은 파일 업로드에 대한 모든 테스트가 실패합니다. Attachment 객체가 생성되었지만 db_file에 데이터가 기록되지 않습니다. 이론은 부모 객체가 먼저 저장된 다음 db_file 물건이 나중에 작성되므로 new_record입니까? false를 반환합니다.

그래서, 실험으로 나는 시도하기로 결정

def save_to_storage 
    if save_attachment? 
     if self.new_record? 
     db_file = DbFile.new :data => temp_data 
     self.class.update_all ['db_file_id = ?', self.db_file_id = db_file.id], ['id = ?', id] 
     else 
     (db_file || build_db_file).data = temp_data 
     db_file.save! 
     self.class.update_all ['db_file_id = ?', self.db_file_id = db_file.id], ['id = ?', id] 
     #end 
    end 
    true 
    end 

가 부분적으로 작동 - db_file가 채워집니다하지만 내가 db_file.save에 오류가! - db_file이 nil이라고 말합니다.

그래서 저는 일종의 방해를 받았습니다. 추가 시행 착오를 할 수는 있지만이 시점에서이 플러그인이 어떻게 작동하는지 제한적으로 이해했습니다. 나는 정말로 그것에 대해 많은 시간을 할애 할 것을 기대하지 않았거나 더 이상 attachment_fu를 탐험하기를 꺼려했지만, 토끼 구멍을 내려야 알아낼 수 있을지 걱정됩니다. 어떤 생각이나 생각?

감사합니다.

+0

참고 : 더 좋은 해결책은 참조 계산 형식을 사용하고 모든 첨부 파일 obj가 동일한 db_file_id를 가리 키도록하는 것입니다. db_file을 가리키는 첨부 파일이없는 경우에만 db_file을 삭제하십시오. Hmm –

답변

0

좋아, 새로운 db_file (우리의 경우에는 낭비입니다)을 만드는 대신 db_file을 가리키는 첨부 파일이 더 이상 없다면 destroy_file을 원숭이 패치했습니다. 누군가가 첨부 파일을 "수정"하도록 허용하는 경우 적합하지 않을 수 있습니다. db_file in situ하지만 우리는 그렇지 않기 때문에 위대한 결과를 얻었습니다.

Technoweenie::AttachmentFu::Backends::DbFileBackend.module_eval do 
    protected 
    def destroy_file 
    if db_file && self.class.count(:conditions =>["id <> ? AND db_file_id = ?", self.id, db_file.id]) == 0 
     db_file.destroy 
    end 
    end 
end 
1

이것은 build_db_file 전화는 의심으로

을 설명 단지 부분적인 반응이다는 build_db_file 호출하는 방법 generated by creating a belongs_to association을 실행합니다. 협회는 여기에서 생성됩니다

def self.included(base) #:nodoc: 
    Object.const_set(:DbFile, Class.new(ActiveRecord::Base)) unless Object.const_defined?(:DbFile) 
    base.belongs_to :db_file, :class_name => '::DbFile', :foreign_key => 'db_file_id' 
end 

그래서 (db_file || build_db_file) 문은 기존의 관련 DbFile 오브젝트를, 아니면 전무의 경우 새로 생성하고, 바이너리 필드 data에 temp_data을 할당합니다. temp_data은 아마도 양식의 데이터가있는 바이트 배열 일 것입니다.

그리고 나는이 질문이 하나 (나는 당신의 질문에 말씀 드릴 수 없습니다) - 왜

db_file = DbFile.new :data => temp_data 

로를 만든 후 db_file.save!를 호출하지 않습니다?

+0

좋은 질문입니다. 그것은 문제를 해결하지는 않지만 내 부분의 버그입니다 :) 감사합니다! –

관련 문제