Antes de entrar en detalles voy directamente al grano: alguien ha descubierto una forma de hacer que Carrierwave guarde los archivos con sus nombres como marca de tiempo o arbitraria cadena que es única para cada archivo?CarrierWave: cree el mismo nombre de archivo único para todos los archivos versionados
De forma predeterminada, Carrierwave guarda cada archivo y sus versiones alternativas en su propio directorio (con el nombre del número de ID del modelo). No soy fanático de esto porque en vez de un directorio con 1,000, para usar un número redondo grande, archivos (en mi caso fotos) en él obtenemos un directorio con 1,000 subdirectorios cada uno con uno o dos archivos. Yuck.
Ahora, cuando se reemplaza el método de su subida por store_dir
a ser algo así como lo siguiente:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}"
end
se termina con el comportamiento exacto que quiero. Todos los archivos (imágenes) entran en una gran carpeta feliz. No más subcarpetas que se quedan cuando el objeto se elimina.
Solo hay un problema. Colisiones de archivos. Si subes delicious_cake.jpg dos veces, el segundo sobrescribirá el primero incluso si son dos imágenes diferentes de delicioso pastel. Es claro por qué el método store_dir
tiene el /#{model.id}
adicional marcado al final del valor que devuelve.
Entonces, ¿qué hacer? Después de leer un poco, descubrí que en el archivo de carga generado hay una solución aparente comentada.
# Override the filename of the uploaded files:
# Avoid using model.id or version_name here, see uploader/store.rb for details.
# def filename
# "something.jpg" if original_filename
# end
Después de un poco de búsqueda me encontré con alguien que había hecho el siguiente
def filename
@name ||= "#{secure_token}.#{file.extension}" if original_filename
end
Esto me hizo pensar, ¿por qué no hacer esto
def filename
@name ||= "#{(Time.now.to_i.to_s + Time.now.usec.to_s).ljust(16, '0')}#{File.extname(original_filename)}"
end
que es cuando las cosas se pusieron terriblemente roto. El problema con esto es que aparentemente se llama al filename
para cada versión del archivo, así que terminamos con nombres de archivo como 1312335603175322.jpg y thumb_1312335603195323.jpg. Observe la pequeña diferencia? Cada nombre de archivo se basa en el momento en que se llamó al filename
para esa versión en particular. Eso no funcionará en absoluto.
A continuación me cansé de usar model.created_at
para la base de la marca de tiempo. Solo un problema, que devuelve nil para la primera versión ya que aún no se ha puesto en la base de datos.
Después de pensar un poco más, decidí probar lo siguiente en el controlador de mi imagen.
def create
if params[:picture] and params[:picture][:image]
params[:picture][:image].original_filename = "#{(Time.now.to_i.to_s + Time.now.usec.to_s).ljust(16, '0')}#{File.extname(params[:picture][:image].original_filename)}"
end
...
Esto reemplaza la propiedad original_filename antes Carrierwave incluso llega a ella por lo que es ser una marca de tiempo. Hace exactamente lo que quiero. La versión original del archivo termina con un nombre como 1312332906940106.jpg y la versión en miniatura (o cualquier otra versión) termina con un nombre como thumb_1312332906940106.jpg.
Pero, esto parece un hack horrible. Esto debería ser parte del modelo, o mejor aún, parte del cargador montado en el modelo.
Entonces, mi pregunta es, ¿hay una mejor manera de lograr esto? ¿Extrañé algo crucial con Carrierwave que hace esto fácil? ¿Hay una manera no tan obvia pero más limpia de resolver esto? El código de trabajo es bueno, pero el código de trabajo que no huele mal es mejor.
Me alegra ver que alguien más aprueba poner todas las imágenes en una gran carpeta feliz. Me alejé de Paperclip debido a su subdirectorio sin sentido. Un nombre de archivo único es todo lo que necesitas. Una computadora no necesita directorios para organizarse, son muy buenos para encontrar cosas. – Starkers