繁体   English   中英

Rails,Attachment_fu-数据库存储附件的深层副本

[英]Rails, Attachment_fu - deep copy of database storage attachments

我有一个模型,比方说附件,该模型使用attachment_fu接受用户上传的文件。 我想对附件进行“深复制”(或在Ruby-ese中进行深克隆),从而在“ db_files”表中创建一个全新的二进制对象。

我发现这还不能解决。 该博客文章: http : //www.williambharding.com/blog/rails/rails-faster-clonecopy-of-attachment_fu-images/

显示据称可用于基于文件系统的存储的方法。 对于基于数据库的存储,“深度复制”失败。 创建了一个新的“附件”,但它使用了预先存在的db_file_id,因此执行了浅表复制。

在attachment_fu的db_file_backend.rb内部,我看到了save方法:

      # 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的一些Ruby元编程魔术速记,尽管我无法确认这一点(获取源代码未提及此内容,也无法在Google上找到它)。

我不太确定它在做什么,但是我的理论是,作为“深度复制”尝试的一部分(在链接的代码中),正在从源obj复制db_file,因此它只是触发保存而不是触发创造。

我最初的理论是,在进行深层复制尝试时,父(附件)对象将被设置为“新”,因此我做了类似的事情:

 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为nil。

所以,我有点受阻。 我可以做一些进一步的试验和错误,但是在这一点上,我对这个插件的工作原理了解有限。 我真的没想到或不想花很多时间在上面,所以我不愿意尝试进一步探索attachment_fu,但恐怕我不得不走到兔子洞里去弄清楚。 有什么想法或想法吗?

谢谢!!

这只是解释build_db_file调用的部分响应

正如您所怀疑的那样, build_db_file调用执行了一个通过创建belongs_to关联生成的方法。 关联在这里创建:

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对象,或者如果它为nil,则创建一个新的对象,并将temp_data分配给其二进制字段data temp_data可能是字节数组,其中包含来自表单的数据。

我有一个问题(我无法对您的问题发表评论)-为什么不致电db_file.save! 用创建之后

db_file = DbFile.new :data => temp_data

好的,因此,除了弄清楚如何创建新的db_file(在我们的特定情况下这是浪费的)之外,我只是用猴子修补了destroy_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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM