我有一个模型,假设附件,使用attachment_fu接受来自用户的文件上传。我想“深拷贝”(或在红宝石-ESE,深克隆)的附件,从而在“DB_FILES”表创建一个完全新的二进制对象。

我发现,这是不太一个解决的问题呢。该博客文章: http://www.williambharding.com/blog /导轨/轨道-更快clonecopy-的-attachment_fu图像/

可见,据称适用于基于文件系统的存储的方法。对于基于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”是一些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是nil

所以,我有点陷入困境。我可以做一些进一步的试验和错误,但在这一点上,我打我的这个插件是如何工作的了解有限。我真的没想到还是想在这上面花了这么长时间,所以我不愿意尝试和探索attachment_fu任何进一步的,但恐怕我不得不走下来的兔子洞弄明白。任何意见或想法?

谢谢!

有帮助吗?

解决方案 2

好了,所以,而不是找出如何创建一个新的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

其他提示

这是刚刚说明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对象,或者创建如果它是零一个新的,并且TEMP_DATA分配给它的二进制字段data。所述temp_data大概是字节数组从形式的数据。

和我有一个问题(我不能对你的问题发表评论) - 你为什么不跟

创建后调用db_file.save!
db_file = DbFile.new :data => temp_data

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top