attachment_fu: Saving files with random filenames (using Digest::SHA1)

Hi all,

I'm creating an image uploader of sorts, and would like all of the
filenames of uploaded files to be completely random when saved. I am
fairly new to Ruby, Rails, and attachment_fu, and came up with the
following earliar:

require 'digest/sha1'

class Photo < ActiveRecord::Base
  has_attachment :content_type => :image,
                 :storage => :file_system,
                 :processor => 'ImageScience',
                 :path_prefix => 'public/photos',
                 :thumbnails => { :thumb => '100x100>' }
  validates_as_attachment

  def filename=(new_name)
    new_name =
"#{Digest::SHA1.hexdigest(Time.now.to_s)}#{File.extname(new_name)}"
    write_attribute :filename, sanitize_filename(new_name)
  end
end

This works, creating filenames such as
'4de12252220d679aa99b12be835ab56c7a5f7fc9.png', but it doesn't set the
thumbnail name correctly (i.e:
4de12252220d679aa99b12be835ab56c7a5f7fc9_thumb.png) - instead, it
saves it with the same filename
(4de12252220d679aa99b12be835ab56c7a5f7fc9.png).

Does anyone have any ideas on how I can achieve this?

Thanks.

I figured out how to do it. Here's the code for those who are
interested. Seems to work perfect now and generates the thumbnail
names how it should.

http://pastie.caboo.se/74792

Rob

Hello,

  def filename=(new_name)
    new_name =
"#{Digest::SHA1.hexdigest(Time.now.to_s)}#{File.extname(new_name)}"
    write_attribute :filename, sanitize_filename(new_name)
  end
end

This works, creating filenames such as
'4de12252220d679aa99b12be835ab56c7a5f7fc9.png', but it doesn't set the
thumbnail name correctly (i.e:
4de12252220d679aa99b12be835ab56c7a5f7fc9_thumb.png) - instead, it
saves it with the same filename
(4de12252220d679aa99b12be835ab56c7a5f7fc9.png).

The problem is filename= is sometimes called with the filename of the full image and sometimes called with the thumbnail's filename.

The way to solve this is to change the filename right where it enters the system. Remove your filename= method and add this instead to your model:

   def uploaded_data=(file_data)
     return nil if file_data.nil? || file_data.size == 0
     self.content_type = file_data.content_type
     self.filename = "#{Digest::SHA1.hexdigest(Time.now.to_s)}#{File.extname(file_data.original_filename)}" if respond_to?(:filename)
     if file_data.is_a?(StringIO)
       file_data.rewind
       self.temp_data = file_data.read
     else
       self.temp_path = file_data.path
     end
   end

This is the same as the original implementation but for the third line in the method.

Regards,
Andy Stewart

I figured out how to do it. Here's the code for those who are
interested. Seems to work perfect now and generates the thumbnail
names how it should.

http://pastie.caboo.se/74792

Aha! That's the same solution I came up with -- but cleaner. Nice one.

Regards,
Andy Stewart