2013-02-15 5 views
8

Il sito Web su cui sto lavorando sta attraversando una riprogettazione e, come tale, le immagini degli utenti devono essere ridimensionate. Il sito è attualmente in uso gemma carrierwave per gestire tutte le immagini e video, e ogni immagine ha un file originale con un nome di file univoco in base alla seguente:Ricrea le versioni utilizzando Carrierwave con Ruby

def filename 
    if original_filename 
    if model && model.read_attribute(:user_image).present? 
     model.read_attribute(:user_image) 
    else 
     @name ||= "#{secure_token}.#{file.extension}" if original_filename.present? 
    end 
    end 
end 

e secure_token essere generato da

def secure_token 
    var = :"@#{mounted_as}_secure_token" 
    model.instance_variable_get(var) or model.instance_variable_set(var, SecureRandom.uuid) 
end 

Il compito che è stato creato per fare questo è:

## 
# CarrierWave Amazon S3 File Reprocessor Rake Task 
# 
# Written (specifically) for: 
# - CarrierWave 
# - Ruby on Rails 3 
# - Amazon S3 
# 
# Works with: 
# - Any server of which you have write-permissions in the Rails.root/tmp directory 
# - Works with Heroku 
# 
# Not tested with, but might work with: 
# - Ruby on Rails 2 
# 
# Might work with, after a couple of tweaks: 
# - File System Storage 
# - Cloud Files Storage 
# - GridFS 
# 
# Examples: 
# 
# Reprocess all versions of User#avatar 
# rake carrierwave:reprocess class=User mounted_uploader=avatar 
# 
# Reprocess the versions: thumb, small, medium for User#avatar 
# rake carrierwave:reprocess class=User mounted_uploader=avatar versions='thumb, small, medium' 
# 
# Reprocess for an underlying association, for things like Embedded MongoDB Documents 
# which are models you cannot access directly, but rather through a regular Document 
# 
# Embeds One (picture) Association 
# rake carrierwave:reprocess class=User association=picture mounted_uploader=image versions='thumb, small, medium' 
# 
# Embeds Many (pictures) Association 
# rake carrierwave:reprocess class=User association=pictures mounted_uploader=image versions='thumb, small, medium' 
# 
# WARNING 
# There is an issue with "Rake", that you cannot name your mounted_uploader "file". 
# If you do this, then you will not be able to reprocess images through this rake task 
# class User 
# include Mongoid::Document 
# mount_uploader :file, PictureUploader 
# end 
# 
# This will NOT work with reprocessing through Rake because the mounted_uploader uses the "file" attribute. 

namespace :carrierwave do 

    ## 
    # Only tested with Amazon S3 Storage 
    # Needs some minor modifications if you want to use this for File System Store, Cloud Files and GridFS probably. 
    # This should work without Ruby on Rails as well, just set a different TMP_PATH. 
    desc "Reprocesses Carrier Wave file versions of a given model." 
    task :reprocess => :environment do 

    ## 
    # Load in the OPEN URI library to be able 
    # to pull down and store the original file in a temp directory 
    require 'open-uri' 

    ## 
    # Default constants 
    TMP_PATH   = "#{Rails.root}/tmp/carrierwave" 

    ## 
    # Set environment constants 
    CLASS    = ENV['class'].capitalize 
    ASSOCIATION  = ENV['association'] || nil 
    MOUNTED_UPLOADER = ENV['mounted_uploader'].to_sym 
    VERSIONS   = ENV['versions'].nil? ? Array.new : ENV['versions'].split(',').map {|version| version.strip.to_sym} 

    ## 
    # Find the Model 
    MODEL = Kernel.const_get(CLASS) 

    ## 
    # Create the temp directory 
    %x(mkdir -p "#{TMP_PATH}") 

    ## 
    # Find all records for the provided Model 
    records = MODEL.all 

    ## 
    # Output to console 
    puts "\nCarrier Wave Version Reprocessing!" 
    puts "=======================================" 
    puts "Model:    #{CLASS}" 
    puts "Mounted Uploader: #{MOUNTED_UPLOADER}" 
    puts "Association:  #{ASSOCIATION}" if ASSOCIATION 
    puts "Versions:   #{VERSIONS.empty? ? "all" : VERSIONS.join(', ')}\n\n" 

    ## 
    # Run through all records 
    records.each do |record| 

     ## 
     # Set the mounted uploader object 
     # If it has a one-to-one association (singular) then that object 
     # will be returned and wrapped in an array so we can "iterate" through it below. 
     # 
     # If it has a one-to-many association then it will return the array of associated objects 
     # 
     # If no association is specified, it assumes the amounted uploader is attached to the specified CLASS 
     if ASSOCIATION 
     if ASSOCIATION.singular? 
      objects = [record.send(ASSOCIATION)] 
     else 
      objects = record.send(ASSOCIATION)   
     end 
     else 
     objects = [record] 
     end 

     ## 
     # Iterates through the objects 
     objects.each do |object| 

     ## 
     # Returns the mounted uploader object 
     mounted_object = object.send(MOUNTED_UPLOADER) 

     ## 
     # Retrieve Filename 
     filename = mounted_object.path.split('/').last 

     ## 
     # Output to console 
     puts "Reprocessing: #{filename}" 

     ## 
     # Read out the original file from the remote location 
     # and write it out to the temp directory (TMP_PATH) 
     # This file will be used as the base file to reprocess 
     # the versions. Once all versions have been processed, 
     # this temp file will be directly removed. 
     open(mounted_object.url) do |original_object| 
      File.open(File.join(TMP_PATH, filename), 'w') do |temp_file| 
      temp_file.write(original_object.read) 
      end 
     end 

     ## 
     # By default it will add all available versions to the versions variable 
     # which means that all available versions will be reprocessed. 
     # If the "versions" argument has been provided, then only the specified 
     # version(s) will be set to the versions variable, and thus, only these 
     # will be reprocessed. 
     versions = mounted_object.versions.map {|version| version[0]} 
     versions = VERSIONS unless VERSIONS.empty? 

     ## 
     # Reprocesses the versions 
     versions.each do |version| 
      mounted_object.send(version).cache!(File.open(File.join(TMP_PATH, filename))) 
      mounted_object.send(version).store! 
     end 

     ## 
     # Removes the temp file 
     %x(rm "#{TMP_PATH}/#{filename}") 
     end 
    end 
    end 
end 

Il problema è che mentre crea le nuove immagini, i file vengono salvati con un nuovo nome file piuttosto che seguendo la denominazione descritta nell'uploader di immagini, quindi il sito Web non può trovarli. Di seguito è riportato un esempio di come vengono archiviate le immagini.

Come dovrebbe essere:

del file originale: fdk392ks93_39ei.png

miniature versione: thumb_fdk392ks93_39ei.png

Come è:

del file originale: fdk392ks93_39ei.png

anteprima versione: thumb_fajeilkadifej_jakdjfi.png

Qualsiasi aiuto sarebbe molto apprezzato.

Altre info:

Modello: User

Uploader: user_image (questo è anche il nome della colonna che memorizza il nome della cartella/file)

+0

porzione Modificato: Come dovrebbe essere: del file originale: fdk392ks93_39ei.png versione di anteprima: thumb_fdk392ks93_39ei.png Come è: del file originale: fdk392ks93_39ei.png versione miniature: thumb_fajeilkadifej_jakdjfi.png – CorreyS

risposta

17

Dopo aver chiamato recreate_versions! devi chiamare save! sul modello. Puoi dare un'occhiata a this question dove qualcuno ha chiesto praticamente la stessa cosa.

8

Il README afferma chiaramente come ricreare versioni Carrierwave:

https://github.com/jnicklas/carrierwave/blob/master/README.md

"si potrebbe arrivare ad una situazione in cui si desidera retroattivamente cha creare una versione o aggiungerne una nuova. Puoi usare le recreate_versions! metodo per ricreare le versioni dal file di base. Ciò utilizza un approccio ingenuo che caricherà di nuovo ed elabora la versione specificata o tutte le versioni, se nessuna di esse viene passata come argomento.

instance = MyUploader.new 
instance.recreate_versions!(:thumb, :large) 

o su un uploader montato:

User.all.each do |user| 
    user.avatar.recreate_versions! 
end 
+1

Ho già provato questo all'interno del modello, ma non tenere traccia dei nomi dei file. Il codice nella mia domanda funziona, tranne per il fatto che salva le nuove versioni sotto un nome di file completamente diverso, che non consente al codice di identificare che la versione fa parte del modello. – CorreyS

+0

@CorreyS hai mai trovato una soluzione a questo? – Tommyixi

+0

Il mio problema è che avevo l'immagine originale nel vecchio database, dopo aver clonato il vecchio database al codice sorgente più recente, ho bisogno di rigenerare l'immagine della versione di anteprima per chi ha solo l'immagine originale che è stata caricata da carrierwave nell'archivio di Amazon S3. Le .recreate_versions! successo per aiutarmi a generare l'immagine della versione thumbnails che dichiarano nel file uploader. Grazie. –