Tuesday, October 28, 2008

attachment_fu with Optional Attachment...again

I wrote about this previously...attachment_fu is not mean to be used to provide a file attachment as an optional attribute of a model with other attributes. If you want to combine a model with its own attributes and an attachment have a look at Paperclip. attachment_fu is a great plugin but the attachment is supposed to live in its own model.

So why am I writing about this again? Well, recently a project that I had worked on before where someone put the attachment directly in another model was updated and then had some plugin problems. I solved the problems by upgrading some of the plugins, including attachment_fu. This upgrade resulted in further breakage of this attachment_fu within another model / optional attachment problem. Now, attachment_fu calls attr_accessible :uploaded_data from the has_attachment directive so you will have to open up the model for your other attributes for bulk assignment. This will look something like this:

class Document < ActiveRecord::Base
has_attachment :storage => :file_system, :path_prefix => 'public/files'
attr_accessible :your, :other, :attributes, :uploaded_data
end
view raw gistfile1.rb hosted with ❤ by GitHub


And as before, the plugin must be patched to prevent errors that would occur when updating or deleting a model that doesn't have an attachment. The patch is here which works against the current attachment_fu:

Index: lib/technoweenie/attachment_fu/backends/file_system_backend.rb
===================================================================
--- lib/technoweenie/attachment_fu/backends/file_system_backend.rb (revision 15741)
+++ lib/technoweenie/attachment_fu/backends/file_system_backend.rb (working copy)
@@ -60,9 +60,11 @@
protected
# Destroys the file. Called in the after_destroy callback
def destroy_file
- FileUtils.rm full_filename
- # remove directory also if it is now empty
- Dir.rmdir(File.dirname(full_filename)) if (Dir.entries(File.dirname(full_filename))-['.','..']).empty?
+ if filename?
+ FileUtils.rm full_filename
+ # remove directory also if it is now empty
+ Dir.rmdir(File.dirname(full_filename)) if (Dir.entries(File.dirname(full_filename))-['.','..']).empty?
+ end
rescue
logger.info "Exception destroying #{full_filename.inspect}: [#{$!.class.name}] #{$1.to_s}"
logger.warn $!.backtrace.collect { |b| " > #{b}" }.join("\n")
Index: lib/technoweenie/attachment_fu.rb
===================================================================
--- lib/technoweenie/attachment_fu.rb (revision 15741)
+++ lib/technoweenie/attachment_fu.rb (working copy)
@@ -303,7 +303,7 @@
# Returns true if the attachment data will be written to the storage system on the next save
def save_attachment?
- File.file?(temp_path.to_s)
+ return File.file?(temp_path.to_s) if temp_path
end
# nil placeholder in case this field is used in a form.
@@ -344,13 +344,14 @@
# An array of all the tempfile objects is stored so that the Tempfile instance is held on to until
# it's not needed anymore. The collection is cleared after saving the attachment.
def temp_path
+ return nil if temp_paths.empty?
p = temp_paths.first
p.respond_to?(:path) ? p.path : p.to_s
end
# Gets an array of the currently used temp paths. Defaults to a copy of #full_filename.
def temp_paths
- @temp_paths ||= (new_record? || !respond_to?(:full_filename) || !File.exist?(full_filename) ?
+ @temp_paths ||= (new_record? || !respond_to?(:full_filename) || filename.blank? || !File.exist?(full_filename) ?
[] : [copy_to_temp_file(full_filename)])
end
view raw gistfile1.patch hosted with ❤ by GitHub


Now the real question is, why haven't I either 1) fixed this the right way or 2) switched to Paperclip by now? Lack of time and an already existing file structure laid out by attachment_fu I suppose...but this is getting ridiculous.

2 comments:

  1. I am using CommunityEngine which uses attachment_fu. I set it up to allow attachments to be optional. Everything worked fine until I tried to delete or update a record.

    Your patch worked perfectly! Now I can insert, delete, and edit a record with or without an attachment. Thanks so much.

    ReplyDelete