2

私は、attachment_fuを使用してユーザーからのファイルのアップロードを受け入れるモデル、たとえばAttachmentsを持っています。添付ファイルを「ディープコピー」(またはRuby-eseではディープクローン)して、「db_files」テーブルに完全に新しいバイナリオブジェクトを作成したいと思います。

私はそれがまだ完全に解決された問題ではないことを発見しました。このブログ投稿: http ://www.williambharding.com/blog/rails/rails-faster-clonecopy-of-attachment_fu-images/

ファイルシステムベースのストレージで機能するとされるメソッドを示します。dbベースのストアの場合、「ディープコピー」は失敗します。新しい「添付ファイル」が作成されますが、既存の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で見つけることもできません)。

それが何をしているのかよくわかりませんが、私の理論では、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

これは実際には複製されたオブジェクトに対しては正常に機能しますが、残念ながら、複製されていない通常のファイルアップロードのすべてのテストは失敗します。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をこれ以上探求するのは気が進まないが、それを理解するためにうさぎの穴を下る必要があるのではないかと心配している。何かアイデアや考えはありますか?

ありがとう!!

4

2 に答える 2

1

これは、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はおそらく、フォームからのデータを含むバイト配列です。

そして、私は1つの質問があります(私はあなたの質問にコメントすることはできません)-db_file.save!それを作成した後に電話してみませんか

db_file = DbFile.new :data => temp_data

于 2010-02-09T15:23:25.757 に答える
0

さて、新しい db_file を作成する方法を考える代わりに (これは私たちの特定のケースでは無駄です)、destroy_file にモンキー パッチを適用して、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
于 2010-02-13T03:28:29.513 に答える