Rails, Attachment_fu - tiefere Kopie der Datenbank-Speicher-Anhänge
-
18-09-2019 - |
Frage
ich ein Modell haben, lassen Sie uns Attachments sagen, dass attachment_fu verwendet Datei-Uploads vom Benutzer zu akzeptieren. Ich möchte „tiefere Kopie“ (oder in Ruby-ese, tiefere Klon) eine Anlage, so dass ein völlig neues binäres Objekt in der „db_files“ Tabelle erstellen.
Ich habe festgestellt, dass es nicht ganz ein gelöstes Problem noch ist. Dieses Blog-Posting: http://www.williambharding.com/blog / Schienen / Schienen-schneller-clonecopy-of-attachment_fu-images /
Zeigt eine Methode, die für das Dateisystem-basierter Speicher angeblich arbeitet. Für db-basierten Geschäfte, schlägt die „tiefe Kopie“. Eine neue „Anlage“ wird erstellt, aber es nutzt die bereits vorhandenen db_file_id, wodurch eine flache Kopie durchgeführt wird.
Innerhalb attachment_fu der db_file_backend.rb Ich sehe die speichern Methode:
# Saves the data to the DbFile model
def save_to_storage
if save_attachment?
(db_file || build_db_file).data = temp_data
db_file.save!
self.class.update_all ['db_file_id = ?', self.db_file_id = db_file.id], ['id = ?', id]
end
true
end
Also, ich versuche, diese zu entschlüsseln, und ich glaube „build_db_file“ einige metaprogramming magische Abkürzung für DbFile.new Ruby ist, obwohl ich das nicht bestätigen kann (greppen die Quelle nicht auf diesen Aspekt zeigt, noch kann ich es auf Google zu finden) .
Ich bin nicht ganz sicher, was es tut, aber meine Theorie ist, dass die DB_File von der Quelle des „Deep Kopie“ Versuchs (in dem verknüpften Code) obj als Teil kopiert wird somit einfach auslöst eine sparen anstelle eines erstellen.
war Meine erste Theorie, dass die Eltern (Attachment) Objekt würde auf „neu“ auf eine tiefe Kopie Versuch, so habe ich so etwas wie:
def save_to_storage
if save_attachment?
if self.new_record?
db_file = DbFile.new :data => temp_data
self.class.update_all ['db_file_id = ?', self.db_file_id = db_file.id], ['id = ?', id]
end
end
true
end
Das funktioniert tatsächlich für geklonte Objekte in Ordnung, aber leider alle Tests für die regelmäßige, nicht geklont das Hochladen von Dateien fehlschlagen. Das Attachment-Objekt wird erstellt, aber keine Daten geschrieben wird DB_File. Theorie ist, dass das übergeordnete Objekt zuerst gespeichert wird, dann ist die DB_File Sachen später geschrieben wird, so new_record? false zurück.
So, als ein Experiment habe ich beschlossen, versuchen:
def save_to_storage
if save_attachment?
if self.new_record?
db_file = DbFile.new :data => temp_data
self.class.update_all ['db_file_id = ?', self.db_file_id = db_file.id], ['id = ?', id]
else
(db_file || build_db_file).data = temp_data
db_file.save!
self.class.update_all ['db_file_id = ?', self.db_file_id = db_file.id], ['id = ?', id]
#end
end
true
end
Das funktioniert zum Teil - die DB_File bevölkert wird, aber dann bekomme ich einen Fehler auf db_file.save! -., Dass DB_File sagen will, ist gleich Null
Also, ich bin irgendwie zunichte gemacht. Ich kann einen weiteren Versuch und Irrtum tun, aber an diesem Punkt habe ich mein begrenztes Verständnis dafür, wie dieses Plugin funktioniert getroffen. Ich habe wirklich nicht erwartet, oder wollen sie so viel Zeit verbringen, so bin ich nur ungern weiter zu versuchen und erkunden attachment_fu, aber ich fürchte, ich werde in den Kaninchenbau haben zu gehen, um es herauszufinden. Irgendwelche Ideen oder Gedanken?
Danke !!
Lösung 2
Okay, also statt herauszufinden, wie eine neue DB_File zu schaffen (was in unserem speziellen Fall verschwenderisch ist), habe ich nur Affen gepatcht destroy_file, um nur die DB_File zu löschen, wenn es keine weiteren Befestigungssätze sind auf sie zeigen. Dies kann nicht sinnvoll sein, wenn Sie jemand erlauben, eine Anlage zu „modifizieren“ DB_File in situ , aber da wir dies nicht tun, funktioniert dies sehr gut.
Technoweenie::AttachmentFu::Backends::DbFileBackend.module_eval do
protected
def destroy_file
if db_file && self.class.count( :conditions =>["id <> ? AND db_file_id = ?", self.id, db_file.id] ) == 0
db_file.destroy
end
end
end
Andere Tipps
Dies ist nur eine Teilantwort Erläuterung des build_db_file
Anruf
Wie Sie vermutet, führt die build_db_file
Aufruf einer Methode erzeugt durch die Schaffung ein belongs_to
Verein . Der Verein wird hier erstellt:
def self.included(base) #:nodoc:
Object.const_set(:DbFile, Class.new(ActiveRecord::Base)) unless Object.const_defined?(:DbFile)
base.belongs_to :db_file, :class_name => '::DbFile', :foreign_key => 'db_file_id'
end
So ist die (db_file || build_db_file)
Anweisung nimmt ein vorhandenes zugehöriges DbFile
Objekt oder einen neuen erstellt, wenn es gleich Null ist, und weist die TEMP_DATA seines Binärfelds data
. Die temp_data
ist wahrscheinlich der Byte-Array mit den Daten aus dem Formular.
Und ich habe eine Frage (ich nicht auf Ihre Frage äußern können) - warum Sie db_file.save!
nicht aufrufen, nachdem sie mit
db_file = DbFile.new :data => temp_data