<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -49,6 +49,7 @@ has_attachment(options = {})
                       # Defaults to :db_file.  Options are :file_system, :db_file, and :s3.
     :processor        # Sets the image processor to use for resizing of the attached image.
                       # Options include ImageScience, Rmagick, and MiniMagick.  Default is whatever is installed.
+    :uuid_primary_key # If your model's primary key is a 128-bit UUID in hexadecimal format, then set this to true.
     
 
   Examples:</diff>
      <filename>README</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,6 @@
 require 'ftools'
+require 'digest/sha2'
+
 module Technoweenie # :nodoc:
   module AttachmentFu # :nodoc:
     module Backends
@@ -28,16 +30,39 @@ module Technoweenie # :nodoc:
       
         # The attachment ID used in the full path of a file
         def attachment_path_id
-          ((respond_to?(:parent_id) &amp;&amp; parent_id) || id).to_i
+          ((respond_to?(:parent_id) &amp;&amp; parent_id) || id) || 0
         end
       
-        # by default paritions files into directories e.g. 0000/0001/image.jpg
-        # to turn this off set :partition =&gt; false
+        # Partitions the given path into an array of path components.
+        #
+        # For example, given an &lt;tt&gt;*args&lt;/tt&gt; of [&quot;foo&quot;, &quot;bar&quot;], it will return
+        # &lt;tt&gt;[&quot;0000&quot;, &quot;0001&quot;, &quot;foo&quot;, &quot;bar&quot;]&lt;/tt&gt; (assuming that that id returns 1).
+        #
+        # If the id is not an integer, then path partitioning will be performed by
+        # hashing the string value of the id with SHA-512, and splitting the result
+        # into 4 components. If the id a 128-bit UUID (as set by :uuid_primary_key =&gt; true)
+        # then it will be split into 2 components.
+        # 
+        # To turn this off entirely, set :partition =&gt; false.
         def partitioned_path(*args)
           if respond_to?(:attachment_options) &amp;&amp; attachment_options[:partition] == false 
             args
-          else 
-            (&quot;%08d&quot; % attachment_path_id).scan(/..../) + args
+          elsif attachment_options[:uuid_primary_key]
+            # Primary key is a 128-bit UUID in hex format. Split it into 2 components.
+            path_id = attachment_path_id.to_s
+            component1 = path_id[0..15] || &quot;-&quot;
+            component2 = path_id[16..-1] || &quot;-&quot;
+            [component1, component2] + args
+          else
+            path_id = attachment_path_id
+            if path_id.is_a?(Integer)
+              # Primary key is an integer. Split it after padding it with 0.
+              (&quot;%08d&quot; % path_id).scan(/..../) + args
+            else
+              # Primary key is a String. Hash it, then split it into 4 components.
+              hash = Digest::SHA512.hexdigest(path_id.to_s)
+              [hash[0..31], hash[32..63], hash[64..95], hash[96..127]] + args
+            end
           end
         end
       </diff>
      <filename>lib/technoweenie/attachment_fu/backends/file_system_backend.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,5 @@
 require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
+require 'digest/sha2'
 
 class FileSystemTest &lt; Test::Unit::TestCase
   include BaseAttachmentTests
@@ -77,4 +78,66 @@ class FileSystemTest &lt; Test::Unit::TestCase
   end
   
   test_against_subclass :test_should_delete_old_file_when_renaming, FileAttachment
-end
\ No newline at end of file
+  
+  def test_path_partitioning_works_on_integer_id(klass = FileAttachment)
+    attachment_model klass
+    
+    # Create a random attachment object, doesn't matter what.
+    attachment = upload_file :filename =&gt; '/files/rails.png'
+    old_id = attachment.id
+    attachment.id = 1
+    
+    begin
+      assert_equal [&quot;0000&quot;, &quot;0001&quot;, &quot;bar.txt&quot;], attachment.send(:partitioned_path, &quot;bar.txt&quot;)
+    ensure
+      attachment.id = old_id
+    end
+  end
+  
+  test_against_subclass :test_path_partitioning_works_on_integer_id, FileAttachment
+  
+  def test_path_partitioning_with_string_id_works_by_generating_hash(klass = FileAttachmentWithStringId)
+    attachment_model klass
+    
+    # Create a random attachment object, doesn't matter what.
+    attachment = upload_file :filename =&gt; '/files/rails.png'
+    old_id = attachment.id
+    attachment.id = &quot;hello world some long string&quot;
+    hash = Digest::SHA512.hexdigest(&quot;hello world some long string&quot;)
+    
+    begin
+      assert_equal [
+          hash[0..31],
+          hash[32..63],
+          hash[64..95],
+          hash[96..127],
+          &quot;bar.txt&quot;
+        ], attachment.send(:partitioned_path, &quot;bar.txt&quot;)
+    ensure
+      attachment.id = old_id
+    end
+  end
+  
+  test_against_subclass :test_path_partitioning_with_string_id_works_by_generating_hash, FileAttachmentWithStringId
+  
+  def test_path_partition_string_id_hashing_is_turned_off_if_id_is_uuid(klass = FileAttachmentWithUuid)
+    attachment_model klass
+    
+    # Create a random attachment object, doesn't matter what.
+    attachment = upload_file :filename =&gt; '/files/rails.png'
+    old_id = attachment.id
+    attachment.id = &quot;0c0743b698483569dc65909a8cdb3bf9&quot;
+    
+    begin
+      assert_equal [
+          &quot;0c0743b698483569&quot;,
+          &quot;dc65909a8cdb3bf9&quot;,
+          &quot;bar.txt&quot;
+        ], attachment.send(:partitioned_path, &quot;bar.txt&quot;)
+    ensure
+      attachment.id = old_id
+    end
+  end
+  
+  test_against_subclass :test_path_partition_string_id_hashing_is_turned_off_if_id_is_uuid, FileAttachmentWithUuid
+end</diff>
      <filename>test/backends/file_system_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -44,6 +44,38 @@ class FileAttachment &lt; ActiveRecord::Base
   validates_as_attachment
 end
 
+class FileAttachmentWithStringId &lt; ActiveRecord::Base
+  set_table_name 'file_attachments_with_string_id'
+  has_attachment :path_prefix =&gt; 'vendor/plugins/attachment_fu/test/files', :processor =&gt; :rmagick
+  validates_as_attachment
+  
+  before_validation :auto_generate_id
+  before_save :auto_generate_id
+  @@last_id = 0
+  
+  private
+    def auto_generate_id
+      @@last_id += 1
+      self.id = &quot;id_#{@@last_id}&quot;
+    end
+end
+
+class FileAttachmentWithUuid &lt; ActiveRecord::Base
+  set_table_name 'file_attachments_with_string_id'
+  has_attachment :path_prefix =&gt; 'vendor/plugins/attachment_fu/test/files', :processor =&gt; :rmagick, :uuid_primary_key =&gt; true
+  validates_as_attachment
+  
+  before_validation :auto_generate_id
+  before_save :auto_generate_id
+  @@last_id = 0
+  
+  private
+    def auto_generate_id
+      @@last_id += 1
+      self.id = &quot;%0127dx&quot; % @@last_id
+    end
+end
+
 class ImageFileAttachment &lt; FileAttachment
   has_attachment :path_prefix =&gt; 'vendor/plugins/attachment_fu/test/files',
     :content_type =&gt; :image, :resize_to =&gt; [50,50]</diff>
      <filename>test/fixtures/attachment.rb</filename>
    </modified>
    <modified>
      <diff>@@ -22,6 +22,19 @@ ActiveRecord::Schema.define(:version =&gt; 0) do
     t.column :type,            :string
     t.column :aspect_ratio,    :float
   end
+  
+  create_table :file_attachments_with_string_id, :id =&gt; false, :force =&gt; true do |t|
+    t.column :id,              :string
+    t.column :parent_id,       :string
+    t.column :thumbnail,       :string 
+    t.column :filename,        :string, :limit =&gt; 255
+    t.column :content_type,    :string, :limit =&gt; 255
+    t.column :size,            :integer
+    t.column :width,           :integer
+    t.column :height,          :integer
+    t.column :type,            :string
+    t.column :aspect_ratio,    :float
+  end
 
   create_table :gd2_attachments, :force =&gt; true do |t|
     t.column :parent_id,       :integer
@@ -105,4 +118,4 @@ ActiveRecord::Schema.define(:version =&gt; 0) do
     t.column :type,            :string
     t.column :aspect_ratio,    :float
   end
-end
\ No newline at end of file
+end</diff>
      <filename>test/schema.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>806fb742ecdb53227610b9a7fc67fdd176d3f271</id>
    </parent>
  </parents>
  <author>
    <name>Hongli Lai (Phusion)</name>
    <email>hongli@phusion.nl</email>
  </author>
  <url>http://github.com/isaacfeliu/attachment_fu/commit/2c164b6854b606665934422f5c27e19546eb03cf</url>
  <id>2c164b6854b606665934422f5c27e19546eb03cf</id>
  <committed-date>2009-02-12T17:36:31-08:00</committed-date>
  <authored-date>2008-09-23T06:52:29-07:00</authored-date>
  <message>Add support for models that have a string as primary key.

Signed-off-by: rick &lt;technoweenie@gmail.com&gt;</message>
  <tree>93e2d47445360a8e3d5af10025136b82eee62455</tree>
  <committer>
    <name>rick</name>
    <email>technoweenie@gmail.com</email>
  </committer>
</commit>
