Thursday, May 12, 2011

Paperclip: How to delete an attachment?

Paperclip (https://github.com/thoughtbot/paperclip) is a great gem. I use it all the time in my rails projects.

One constant need I have is to be able to remove a picture I added to one of my model objects while editing it. Say I uploaded a profile picture and now I want to remove it...

While browsing for a solution, I ran into this: http://railsforum.com/viewtopic.php?id=30349.
The solution is nice but I'd hate to repeat it in every model object where I use an attachment. Some models have more than one attachment too...

So I converted the proposed solution into a module, saved it as 'image_clearer.rb' under the 'lib' directory in my rails project:


module ImageClearer
  def self.included(host_class)
    host_class.extend(ClassMethods)
  end
  module ClassMethods
    def clear_image_for(field)
      attr_accessor "clear_#{field}"
      before_validation "check_for_clear_#{field}"
      define_method("clear_#{field}=") do |val|
        instance_variable_set("@clear_#{field}", !val.to_i.zero?)
      end
      define_method("clear_#{field}") do
        !!instance_variable_get("@clear_#{field}")
      end
      alias_method "clear_#{field}?", "clear_#{field}"
      class_eval <<-"END"
        def check_for_clear_#{field}
          if clear_#{field}?
            self.#{field} = nil
          end
        end
      END
   
    end
  end
end


Then in the model where I have an attachment:


require 'image_clearer'
class Product < ActiveRecord::Base
 include ImageClearer
      has_attached_file :photo,
        :url => "/uploaded/:class/:attachment/:id/:style_:basename.:extension"
  end
  clear_image_for :photo

and in my edit view, all I have to do is:

...
 <% if @product.photo.file? -%>
      <%= f.check_box :clear_photo -%>Delete photo
  <% end -%>


If you have more than one attachment in your model, you can use it as:
 clear_image_for  :attachment1
 clear_image_for  :attachment2