I have a model, let's say Attachments, that uses attachment_fu to accept file uploads from the user. I want to "deep copy" (or in Ruby-ese, deep clone) an Attachment, thus creating a completely new binary object in the "db_files" table.
I've found that it is not quite a solved problem yet. This blog posting: http://www.williambharding.com/blog/rails/rails-faster-clonecopy-of-attachment_fu-images/
Shows a method that allegedly works for filesystem based storage. For db-based stores, the "deep copy" fails. A new "Attachment" is created but it uses the pre-existing db_file_id, thus performing a shallow copy.
Inside attachment_fu's db_file_backend.rb I see the save method:
# 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
So, I am trying to decipher this and I believe "build_db_file" is some Ruby metaprogramming magic shorthand for DbFile.new although I cannot confirm this (grepping the source shows no mention of this, nor can I find it on google).
I'm not quite sure what it is doing, but my theory is that the db_file is being copied from the source obj as part of the "Deep copy" attempt (in the linked code) thus it is simply triggering a save instead of a create.
My initial theory was that the parent (Attachment) object would be set to "new" upon a deep copy attempt, thus I did something like:
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
This actually works fine for cloned objects but unfortunately all the tests for regular, non cloned file uploads fail. The Attachment object is created but no data is written to db_file. Theory is that the parent object is saved first, then the db_file stuff is written later, thus new_record? returns false.
So, as an experiment I decided to try:
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
That works partially - the db_file is populated but then I get an error on db_file.save! - saying that db_file is nil.
So, I'm sort of stymied. I can do some further trial and error but at this point I've hit my limited understanding of how this plugin works. I really didn't expect or want to spend this much time on it so I am reluctant to try and explore attachment_fu any further, but I'm afraid I'm going to have to go down the rabbit hole to figure it out. Any ideas or thoughts?
Thanks!!