Domanda

Ho un modello, diciamo allegati, che attachment_fu utilizza per accettare il caricamento di file da parte dell'utente. Voglio "copia completa" (o in Ruby-ese, profondo clone) di un allegato, creando così un nuovo oggetto binario nella tabella "db_files".

ho scoperto che non è un bel problema risolto ancora. Questo post di blog: http://www.williambharding.com/blog / rotaie / rotaie-veloce-clonecopy-of-attachment_fu-images /

mostra un metodo che presumibilmente lavora per la conservazione a base filesystem. Per i negozi db-based, il "copia completa" fallisce. Un nuovo "Allegato" è stato creato ma utilizza la db_file_id preesistente, svolgendo così una copia.

All'interno db_file_backend.rb di attachment_fu vedo il metodo 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

Quindi, io sto cercando di decifrare questo e credo "build_db_file" è un po 'Rubino metaprogrammazione scorciatoia magica per DbFile.new anche se non posso confermarlo (grep la fonte non mostra alcuna menzione di questo, né posso trovare su google) .

Non sono molto sicuro di quello che sta facendo, ma la mia teoria è che il DB_File viene copiato dalla sorgente obj come parte del tentativo di "copia completa" (nel codice collegato) così è semplicemente innescando un salvataggio invece di un creare.

La mia teoria iniziale era che il (Allegato) oggetto padre sarebbe stato impostato su "nuovo" su un tentativo di copia completa, quindi ho fatto qualcosa di simile:

 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

Questo funziona davvero bene per gli oggetti clonati ma purtroppo tutti i test per il caricamento di file regolari, non clonati sicuro. L'oggetto allegato si crea, ma non i dati vengono scritti DB_File. La teoria è che l'oggetto padre viene salvato prima, poi la roba DB_File è scritto in seguito, in tal modo new_record? restituisce false.

Quindi, come un esperimento ho deciso di provare:

  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

Che funziona parzialmente - l'DB_File è popolata ma poi ho un errore su db_file.save! -. Dicendo che DB_File è pari a zero

Quindi, sto sorta di ostacolati. Posso fare qualche ulteriore prova ed errore, ma a questo punto ho colpito la mia limitata comprensione di come funziona questo plugin. Io davvero non mi aspettavo o voglia di spendere così tanto tempo su di esso, quindi sono riluttanti a provare ed esplorare attachment_fu oltre, ma ho paura che ho intenzione di andare nella tana del coniglio per capirlo. Tutte le idee o pensieri?

Grazie !!

È stato utile?

Soluzione 2

Va bene, così, invece di capire come creare un nuovo DB_File (che è uno spreco nel nostro caso particolare), ho appena scimmia-patched destroy_file per eliminare solo la DB_File se non ci sono più record di attacco che puntano ad esso. Questo potrebbe non essere indicato se si consente a qualcuno di "modificare" un allegato DB_File in situ , ma dal momento che non lo facciamo, questo funziona alla grande.

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

Altri suggerimenti

Questa è solo una risposta parziale che spiega la chiamata build_db_file

Come si sospetta, la chiamata build_db_file esegue un metodo generato con la creazione di un'associazione belongs_to . L'associazione è creato qui:

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

Quindi, la dichiarazione (db_file || build_db_file) prende un oggetto DbFile associato esistente o ne crea uno nuovo se è pari a zero, e assegna il temp_data al suo campo data binario. Il temp_data è probabilmente l'array di byte con i dati dal modulo.

E ho una domanda (non posso commentare sulla sua domanda) - perché non chiami db_file.save! dopo aver creato con

db_file = DbFile.new :data => temp_data

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top