2012-04-20 10 views
10

Tengo un modelo con un clip de papel avatar adjunto. Ahora tiene una ruta estándar normalPaperclip + S3: migración de archivos existentes de uno: formato de ruta a otro

has_attached_file :avatar, 
    :path => "/:id-:style-:filename" 

¿Qué necesito para pasar a un ofuscado uno

has_attached_file :avatar, 
    :path => "/:id-:hash.:extension" 
    :hash_secret => 'asecuresecret' 

todo funciona bien con nuevas imágenes, pero ¿cómo puedo migrar los archivos existentes almacenados en S3 para la nuevo formato de ruta, es decir, cambiarles el nombre?

estoy usando un clip 2.7 y 3.2 Rieles

Gracias !!!

+0

Para los interesados, pasar de hash a no hash es un poco más interesante y el mejor método que he encontrado es crear un nuevo 'has_attached_file' para realizar la migración. –

Respuesta

3

Esta tarea de rake debería hacer el truco. Lo intenté con aws-sdk 1.5.2 y ruby ​​1.9.3p194.

El new_key debe asignarse a su nueva ruta de clip. No olvide configurar :acl según sus necesidades.

namespace :data do 
    desc 'aws images migration' 
    task :migrate_images do |t, args| 
    s3 = AWS::S3.new(:access_key_id => 'XXX', :secret_access_key => 'XXX') 
    bucket = s3.buckets['your-bucket-name'] 
    bucket.objects.each do |object| 
     new_key = object.key.gsub(........) 
     new_object = bucket.objects[new_key] 
     object.copy_to new_object, {:acl => :public_read} 
    end 
    end 
end 

El archivo original debe eliminarse manualmente o con una tarea similar, una vez que esté seguro de que el nuevo archivo es correcto.

+0

Probado con '' aws-sdk'' 1.26 y ruby ​​2.0. ¡Gracias y perdón por el retraso en la aceptación! – dgilperez

0

Escribiría una tarea de rake (o simplemente una secuencia de comandos simple, si lo prefiere, para ejecutarla en el contexto de rails). Si está utilizando la gema aws-s3, repita las instancias del modelo que sabe que tienen el formato de ruta antiguo o intente escribir alguna condición en el nombre de archivo para hacerlas coincidir, y el movimiento de uno en uno.

Model.find_in_batches(:batch_size => 500, 
     :conditions => "avatar_filename like 'SOMETHING_MATCHING'") do |o| 
    AWS::S3::S3Object.rename(old_path(o.avatar), o.avatar.url, 'BUCKET_NAME') 
end 

Si ya ha configurado avatar con la nueva definición de la ruta, escribir un método que se puede construir el antiguo camino basado en las propiedades de avatar.

Puede leer los documentos de gemas de aws-s3 here para ver cómo establecer una conexión con su cuenta S3.

9

Si quiere trabajar solo con Paperclip y no le preocupa volver a cargar, seguí otro enfoque.

Supongamos que tiene lo siguiente:

class User 
    has_attached_file :image, path: "/:old_path/:filename" 
    ... 
end 

y desea migrar a la nueva ruta: "/:new_path/:filename"

mi sugerencia es crear un FakeUser con el camino viejo y cambiarlo en el usuario modelo.

class FakeUser 
    self.table_name = :users 
    has_attached_file :image, path: "/:old_path/:filename" 
    ... 
end 

class User 
    has_attached_file :image, path: "/:new_path/:filename" 
    ... 
end 

Ahora se puede escribir la siguiente migración:

FakeUser.find_each do |fake_user| 
    User.find(fake_user.id).update(image: fake_user.image) 
    fake_user.image.destroy 
end 

continuación, puede eliminar el modelo FakeUser una vez finalizada la migración.

Por cierto, este enfoque funcionará perfectamente también para migrar desde el sistema de archivos local a S3 o viceversa.

+3

esto funcionó para mí, incluso podría simplificarlo heredando el modelo falso del modelo real 'clase FakeUser silva96

+0

¡Muy buena solución para migrar todos tus archivos! Mejor que los guiones que he visto. –

Cuestiones relacionadas