Question

J'ai un modèle, disons les pièces jointes, que attachment_fu utilise pour accepter le téléchargement de fichiers de l'utilisateur. Je veux « copie en profondeur » (ou Ruby-ese, clone profond) une pièce jointe, créant ainsi un objet binaire complètement nouveau dans le tableau « DB_FILES ».

Je l'ai trouvé qu'il est pas tout à fait un problème encore résolu. Ce blog annonce: http://www.williambharding.com/blog / rails / rails plus rapide clonecopy-de-attachment_fu-images /

Affiche une méthode qui fonctionne prétendument pour le stockage à base de système de fichiers. Pour les magasins à base db, la « copie en profondeur » échoue. est créé une nouvelle « pièce jointe », mais il utilise le db_file_id pré-existante, réalisant ainsi une copie superficielle.

A l'intérieur du db_file_backend.rb de attachment_fu Je vois la méthode de sauvegarde:

      # 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

Alors, je suis en train de déchiffrer et je crois « build_db_file » est une abréviation magique metaprogramming Ruby pour DbFile.new bien que je ne peux pas confirmer (grepper la source ne montre aucune mention de cela, et je ne peux trouver sur google) .

Je ne suis pas tout à fait sûr de ce qu'il fait, mais ma théorie est que la db_file est copiée à partir de la source obj dans le cadre de la « copie profonde » tentative (dans le code lié) ainsi déclenche simplement une sauvegarde au lieu d'une création.

Ma théorie initiale était que le parent (pièce jointe) objet serait réglé sur « nouveau » sur une tentative profonde de copie, ainsi que je l'ai fait quelque chose comme:

 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

Cela fonctionne réellement bien pour les objets clonés mais malheureusement, tous les tests réguliers, pour le téléchargement de fichiers non clonés échouent. L'objet de la pièce jointe est créée mais aucune donnée est écrite DB_File. La théorie est que l'objet parent est enregistré d'abord, puis les choses db_file est écrit plus tard, new_record ainsi? retourne false.

Alors, comme une expérience que j'ai décidé d'essayer:

  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

Cela fonctionne en partie - la db_file est peuplée mais je reçois une erreur sur db_file.save! -. Dire que db_file est nul

Alors, je suis un peu contrecarrés. Je peux faire quelques essais et erreurs, mais encore à ce moment que je l'ai frappé ma compréhension limitée de la façon dont ce plugin fonctionne. Je ne m'y attendais pas vraiment ou si vous voulez passer autant de temps à ce sujet donc je suis réticent à essayer d'explorer attachment_fu plus loin, mais je crains que je vais devoir aller dans le trou du lapin pour le comprendre. Toutes les idées ou pensées?

Merci !!

Était-ce utile?

La solution 2

Ok, donc au lieu de trouver comment créer une nouvelle db_file (ce qui est inutile dans notre cas particulier), je viens de singe patché destroy_file seulement supprimer le db_file s'il n'y a pas plus de disques de fixation pointant vers elle. Cela peut ne pas être approprié si vous permettez à quelqu'un de « modifier » une pièce jointe db_file in situ mais puisque nous ne le faisons pas, cela fonctionne très bien.

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

Autres conseils

Ceci est juste une réponse partielle expliquant l'appel build_db_file

Comme vous le soupçonnez, l'appel build_db_file exécute une méthode générée par la création une association de belongs_to . L'association est créée ici:

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

l'instruction (db_file || build_db_file) prend un objet DbFile associé existant ou crée une nouvelle si elle est nulle, et affecte le temp_data à son data de champ binaire. Le temp_data est probablement le tableau d'octets avec les données du formulaire.

Et j'ai une question (je ne peux pas répondre à votre question) - pourquoi ne vous appelez pas db_file.save! après avoir créé avec

db_file = DbFile.new :data => temp_data

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top