Rieles, Attachment_fu - copia en profundidad de la base de datos de almacenamiento de archivos adjuntos

StackOverflow https://stackoverflow.com/questions/2205110

Pregunta

Tengo un modelo, digamos adjuntos, que utiliza attachment_fu para aceptar la carga de archivos de usuario. Quiero "copia en profundidad" (o en Ruby-ese, el clon de profundidad) un archivo adjunto, creando así un nuevo objeto binario en la tabla "DB_FILES".

Me he dado cuenta que no es un gran problema resuelto todavía. Esta entrada de blog: http://www.williambharding.com/blog / carriles / carriles-rápido-clonecopy-de-attachment_fu-images /

muestra un método que supuestamente trabaja para el almacenamiento basado en el sistema de archivos. Para las tiendas basadas en db, la "copia en profundidad" falla. Se crea un nuevo "archivo adjunto" pero utiliza el db_file_id preexistente, realizando así una copia superficial.

Dentro de db_file_backend.rb attachment_fu veo el método 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

Por lo tanto, estoy tratando de descifrar esto y yo creo "build_db_file" es un poco de Rubí metaprogramming abreviada mágica para DbFile.new aunque no puedo confirmar esto (grepping la fuente muestra ninguna mención de esto, ni puedo encontrar en Google) .

No estoy muy seguro de lo que está haciendo, pero mi teoría es que el DB_File se está copiando desde la fuente obj como parte del intento de "copia en profundidad" (en el código relacionado) por lo que es simplemente accionando una mano salvadora en lugar de una creación.

Mi teoría inicial era que el (Anexo) objeto padre se establece en "nuevo" en un intento de copia en profundidad, por lo que he hecho algo como:

 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

En realidad, esto funciona bien para los objetos clonados pero desafortunadamente todas las pruebas para cargas normales, no clonados de archivos falle. Se crea el objeto de fijación, pero no se escriben datos a DB_File. La teoría es que el objeto primario se guarda en primer lugar, a continuación, el material DB_File se escribe más adelante, por lo tanto new_record? devuelve false.

Por lo tanto, como un experimento, decidí probar:

  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

Eso se resuelve parcialmente - el DB_File está poblada pero cuando me siento un error en db_file.save! -. DB_File diciendo que es nulo

Por lo tanto, estoy especie de stymied. Puedo hacer algo más ensayo y error, pero en este momento me he pegado a mi limitada comprensión de cómo funciona este plugin. Realmente no esperaba ni quería gastar tanto tiempo en él, así que soy reacio a probar y explorar attachment_fu más lejos, pero me temo que voy a tener que pasar por el agujero del conejo para averiguarlo. Cualquier ideas o pensamientos?

Gracias !!

¿Fue útil?

Solución 2

De acuerdo, así que en vez de encontrar la manera de crear un nuevo DB_File (que es un desperdicio en nuestro caso particular), acabo de mono-parcheado destroy_file a eliminar sólo el DB_File si no hay más registros de fijación apuntando hacia él. Esto puede no ser apropiado si se permite a alguien para "modificar" un archivo adjunto DB_File In situ pero ya no lo hacemos, esto funciona muy 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

Otros consejos

Esto es sólo una respuesta parcial que explica la llamada build_db_file

Como se sospechaba, el llamado build_db_file ejecuta un método genera creando una asociación belongs_to . Se crea la asociación aquí:

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

Así que la declaración (db_file || build_db_file) toma un objeto asociado DbFile existente o crea uno nuevo si es nulo, y asigna el temp_data a su data campo binario. El temp_data es, probablemente, la matriz de bytes con los datos del formulario.

Y tengo una pregunta (que no puedo comentar sobre su pregunta) - ¿por qué no llamas db_file.save! después de crearlo con

db_file = DbFile.new :data => temp_data

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top