2010-02-05 27 views
2

我有一個模型,讓我們說Attachments,它使用attachment_fu來接受用戶的文件上傳。我想「深層複製」(或在Ruby-ese中深層克隆)Attachment,從而在「db_files」表中創建一個全新的二進制對象。Rails,Attachment_fu - 數據庫存儲附件的深層副本

我發現它還沒有完全解決問題。此博客文章: http://www.williambharding.com/blog/rails/rails-faster-clonecopy-of-attachment_fu-images/

顯示一種據稱可用於基於文件系統的存儲的方法。對於基於數據庫的商店,「深層複製」失敗。創建一個新的「附件」,但它使用預先存在的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」是一些Ruby的元編程魔法速記DbFile.new雖然我不能確認這(grepping的來源顯示沒有提到這一點,我也不能在谷歌上找到它)。

我不太清楚它在做什麼,但我的理論是,db_file是從源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 

這實際上工作正常克隆的對象,但遺憾的是所有針對常規,非克隆文件上傳的測試都會失敗。附件對象已創建,但沒有數據寫入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是零。

所以,我有點困難。我可以做一些進一步的試驗和錯誤,但是現在我已經對我的插件工作原理有了一些瞭解。我真的沒有想到或想要花這麼多時間,所以我不願意嘗試探索attachment_fu,但恐怕我不得不去掉兔子洞來弄清楚。任何想法或想法?

謝謝!

+0

注意:更優雅的解決方案是使用引用計數形式,並使所有Attachment obj指向相同的db_file_id。只有在沒有附件指向它時刪除db_file。嗯 – 2010-02-05 19:36:25

回答

0

好的,所以我沒有搞清楚如何創建一個新的db_file(這在我們的特殊情況下是浪費的),而只是刪除了db_file,如果沒有更多的附件記錄指向它的話。如果您允許某人「修改」附件db_file 原位,但這可能不合適,但由於我們不這樣做,所以這很有用。

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對象,或者創建如果它是零一個新的,和TEMP_DATA分配給它的二進制領域datatemp_data可能是包含表單數據的字節數組。

而且我有一個問題(我不能對你的問題發表評論) - 爲什麼不叫db_file.save!

db_file = DbFile.new :data => temp_data 

創建後?

+0

好問題。這是我的一個錯誤,雖然它不能解決問題:)謝謝! – 2010-02-09 16:54:51