Skip to content

Instantly share code, notes, and snippets.

@basiszwo
Created August 29, 2013 10:07
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save basiszwo/6376337 to your computer and use it in GitHub Desktop.
Save basiszwo/6376337 to your computer and use it in GitHub Desktop.
Carrierwave upload directory partitioning
# thanks to @rainchen
class BaseUploader < CarrierWave::Uploader::Base
storage :file
after :remove, :delete_empty_upstream_dirs
# e.g.: "uploads/venue/photo/000/000/003/thumb_Limoni_-_overall-resized-1.jpg"
def store_dir
"#{base_store_dir}/#{model_id_partition}"
end
def base_store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}"
end
# e.g.: 1234 => "000/001/234"
def model_id_partition
("%09d" % model.id).scan(/\d{3}/).join("/")
end
# tips: https://github.com/jnicklas/carrierwave/wiki/How-to%3A-Make-a-fast-lookup-able-storage-directory-structure
def delete_empty_upstream_dirs
# path = ::File.expand_path(store_dir, root)
# Dir.delete(path) # fails if path not empty dir
# delete partition dir
# e.g.: "111/222/333" => [["111", "222", "333"], ["111", "222"], ["111"]]
id_partitions = model_id_partition.split('/').inject([]) { |_, i| _ << ((_.last || []).dup << i.dup).flatten }.reverse
partition_dirs = id_partitions.map { |_| "#{base_store_dir}/#{_.join("/")}" }
[*partition_dirs, base_store_dir].each do |_path|
path = ::File.expand_path(_path, root)
# debugger if base_store_dir = "uploads/venue/photo"
Dir.delete(path) # fails if path not empty dir, beware ".DS_Store" when in development
end
rescue SystemCallError
true # nothing, the dir is not empty
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment