2009-08-17 10 views
2

Ich habe eine Schienenanwendung, die attachment_fu verwendet. Momentan verwendet es :file_system für den Speicher, aber ich möchte es in :s3 ändern, um eine bessere Skalierung zu ermöglichen, wenn mehr Dateien hochgeladen werden.Was ist mit dem Ändern des Speicherschemas von attachment_fu verbunden?

Was ist damit verbunden? Ich stelle mir vor, dass wenn ich nur den Code um :s3 zu verwenden, alle alten Links gebrochen werden. Muss ich nur die vorhandenen Dateien aus dem Dateisystem in S3 kopieren? Eine Google-Suche hat nicht viel zum Thema gefunden.

Ich würde es vorziehen, die vorhandenen Dateien auf S3 zu verschieben, also ist alles an der gleichen Stelle, aber wenn nötig, können die alten Dateien bleiben, wo sie sind, solange neue S3 gehen.

EDIT: So ist es nicht so einfach wie das Kopieren über die Dateien in S3; Die URLs werden mit einem anderen Schema erstellt. Wenn sie in gespeichert werden, landen die Dateien in Orten wie /public/photos/0000/0001/file.name, aber die gleiche Datei in :s3 kann in 0/1/file.name enden. Ich denke, es ist die Verwendung der ID etwas, und padding es (oder nicht) mit Nullen, aber ich bin mir nicht sicher.

Antwort

4

Das ist richtig. Die IDs werden aufgefüllt mit: file_system storage. Anstatt alle Ihre Dateien umzubenennen, können Sie das s3-Backend-Modul ändern, um auch gepolsterte Zahlen zu verwenden.

Kopieren Sie die partitioned_path Methode von file_system_backend.rb und setzen Sie es in s3_backend.rb.

def partitioned_path(*args) 
     if respond_to?(:attachment_options) && attachment_options[:partition] == false 
     args 
     elsif attachment_options[:uuid_primary_key] 
     # Primary key is a 128-bit UUID in hex format. Split it into 2 components. 
     path_id = attachment_path_id.to_s 
     component1 = path_id[0..15] || "-" 
     component2 = path_id[16..-1] || "-" 
     [component1, component2] + args 
     else 
     path_id = attachment_path_id 
     if path_id.is_a?(Integer) 
      # Primary key is an integer. Split it after padding it with 0. 
      ("%08d" % path_id).scan(/..../) + args 
     else 
      # Primary key is a String. Hash it, then split it into 4 components. 
      hash = Digest::SHA512.hexdigest(path_id.to_s) 
      [hash[0..31], hash[32..63], hash[64..95], hash[96..127]] + args 
     end 
     end 
    end 

Modify s3_backend.rb ‚s full_filename Verfahren den partitioned_path zu verwenden.

def full_filename(thumbnail = nil) 
     File.join(base_path, *partitioned_path(thumbnail_name_for(thumbnail))) 
    end 

attachment_fu wird nun Pfade mit den gleichen Namen erstellen, wie es mit dem file_system Backend haben, so können Sie Ihre Dateien über zu s3 einfach kopieren, ohne alles zu umbenennen.

2

Neben nilbus' Antwort hatte ich s3_backend.rb zu ändern ‚s base_path Methode zurückgeben einen leeren String, andernfalls würde sie die attachment_path_id zweimal einfügen:

def base_path 
    return '' 
end 
2

Was für mich gearbeitet, zusätzlich zu nilbus des Antwort war s3_backend.rb die base_path Methode ändern noch die PATH_PREFIX (die der Tabellenname ist standardmäßig) zu verwenden:

def base_path 
    attachment_options[:path_prefix] 
end 

Und auch, hatte ich dienehmenvon file_system_backend.rb und die eine in s3_backend.rb ersetzen, da sonst partitioned_path immer mein Primary Key ein String war gedacht:

def attachment_path_id 
    ((respond_to?(:parent_id) && parent_id) || id) || 0 
end 
0

Dank für all die Antworten, die sehr geholfen. Es funktionierte auch für mich, aber ich musste dies tun, damit die Option :thumbnail_class funktionierte:

def full_filename(thumbnail = nil) 
    prefix = (thumbnail ? thumbnail_class : self).attachment_options[:path_prefix].to_s 
    File.join(prefix, *partitioned_path(thumbnail_name_for(thumbnail))) 
end