2012-03-29 31 views
19

Necesito copiar un archivo de un objeto de onda portadora a otro. Son diferentes tablas y diferentes tipos de cargadores.¿Cuál es la forma correcta de copiar un archivo de onda transportadora de un registro a otro?

Empecé con:

user.avatar = image.content 

(donde el usuario y la imagen son instancias de modelo, avatar y el contenido se la carrierwave montado uploaders) que funcionaba a veces. Parece funcionar todo el tiempo localmente, con un almacenamiento de archivos, pero intermitente cuando se usa niebla y s3.

En un mailing list post me encontré con este código:

user.avatar = image.content.file 

que colaboró ​​de nuevo a veces.

Mi solución de trabajo hasta ahora es:

require "open-uri" 

begin 
    user.avatar = open(image.url) 
rescue Errno::ENOENT => e 
    begin 
    user.avatar = open(image.path) 
    rescue Errno::ENOENT => e 
    # Ok, whatever. 
    end 
end 

que no sólo es feo, pero que no logra pasar la validación de extensión debido a la apertura de un archivo remoto no mantiene la extensión (jpg, gif, etc. .).

Respuesta

12

¿Quizás una forma de hacerlo sea establecer una URL de imagen remota según the Carrierwave gem documentation?

user.remote_avatar_url = image.url 
+0

¿Tiene imagen image.content.url? No estoy seguro de que esto funcione, ya que avatar tiene muchas versiones con diferentes procesos que necesitan un archivo local para funcionar, y no quiero que ambos registros apunten al mismo archivo, quiero una copia del archivo. – Pablo

+1

La forma en que funciona remote_blah_url es que esencialmente "descarga" el archivo de esa URL y lo vuelve a procesar. Ver http://stackoverflow.com/questions/5007575/how-to-assign-a-remote-file-to-carrierwave, por ejemplo. – Ibrahim

+3

No funciona si la imagen no se sirve a través de HTTP. Obtendrá el siguiente error: 'Icono que intenta descargar un archivo que no se sirve en HTTP' – Pioz

5

Desde soluciones discutidas aquí creé sencilla CopyCarrierwaveFile gema para hacer este uso

es algo como esto:

original_resource = User.last 
new_resource  = User.new 

CopyCarrierwaveFile::CopyFileService.new(original_resource, new_resource, :avatar).set_file  

new_resource.save 
nev_resource.avatar.url # https://...image.jpg 
0

he aquí una solución (aunque hacky) para que no requiere una Solicitud HTTP para recuperar la imagen:

module UploadCopier 
    def self.copy(old, new) 
    new.instance_variable_set('@_mounters', nil) 

    old.class.uploaders.each do |column, uploader| 
     new.send("#{column}=", old.send(column)) 
    end 
    end 
end 

old_user = User.last 
new_user = User.new 
UploadCopier.copy(old_user, new_user) 
new_user.save 
0

Solo quería copiar un avatar referencia de un objeto a otro, y lo que funcionó para mí fue:

objectB.avatar.retrieve_from_store!(objectA.avatar.identifier) 
objectB.save 
1

que necesitaba para copiar una referencia de un modelo a otro modelo y yo estaba con éxito en condiciones de hacerlo de la siguiente manera:

my_new_model.update_column('attachment', my_other_model.attributes["attachment"]); 

En este caso, no me interesaba realmente hacer una copia del archivo, ni me importaba que 2 registros estuvieran ahora vinculados al mismo archivo (mi sistema nunca elimina o modifica los archivos después de cargarlos).

Esto puede ser útil para cualquiera que quiera copiar la referencia a un archivo de un modelo a otro usando el mismo cargador.

+0

No funcionó para mí. https://stackoverflow.com/questions/45901396/carrierwave-sharing-an-image-between-two-models – Dercni

+1

@Dercni hace una buena nota: este método solo funciona si no se utilizan otros campos, excepto el campo 'attachment' determinar dónde se encuentra el archivo. – PressingOnAlways

+0

Bueno, después de horas luchando con la URL remota he decidido usar su solución y tener una ruta común para ambos modelos y simplemente compartir el archivo, como lo ha demostrado. – Dercni

Cuestiones relacionadas