Quantcast
Channel: Ruby – My Programming Blog
Viewing all articles
Browse latest Browse all 12

How to ensure that filename is always unique ? [Ruby]

$
0
0

Hey guys!

Happy New Year! I am glad to be back this year with some interesting news. Thank you for blasting my mailbox with your questions and suggestions! I will do my best to answer all of them as soon as I can!

One of the readers asked me a  question that I  think is very interesting. Moreover, I have faced the same issue recently, and today I want to share it with you.

So topic of today is:

How to ensure filename is always unique ? [Ruby] 

Why is this a problem?

Imagine you are copying a file ‘a.jpg’  in the directory where this file already exist. Some of the systems I know just give you a validation error and ask to rename a file. But it is a good user experience ? I don’t think so.

So what are our options to tackle this issue ?

Option 1. Append some random string to the filename e.g ‘a-asdsds.jpg’

But is it a solution? How random are those strings ? Does this look appealing ?
I think it is a solution, but a pretty ugly one.

Option 2. Append a number to the filename that is incremented with every creation

This solutions is definitely not a new one, it is used by some OS, and I think it might be the easiest and most elegant one. E.g ‘picture.png’ becomes ‘picture-1.png’ and then ‘picture-2.png’.

Any other options you can think of ? Please comment and let me know ;)

Meanwhile we will go with Option 2.

Next question is:

Based on what should we increment this number ?

Some of the solutions I have seen before is based on counting number of files, and then incrementing count by one. This makes sense, but unfortunately this won’t work. ;)

Why?

Lets say I have files ‘a-1.jpg’, ‘a-2.jpg’,a-3.jpg’. Count is 3 here. Now Imagine I have  deleted file ‘a-2.jpg’, and I want to add a new file. So current Count is 2 (a-1 and a-3), so my next filename based on logic should be a-3 (we increment count by 1 -> 2+1), but it is already taken.

Here is the strategy that I think might work:

Lets say we again have 3 files –  ‘a-1.jpg’, ‘a-2.jpg’,a-3.jpg’. We will take the numbers of those files (1,2,3) find the largest and increment it by one. So if we apply to it to previous use-case – we will delete ‘a-2′, but largest number is still 3, so new filename will be ‘a-4′.

What do you think ?

I know that most of you are code-maniacs and want to dig into code right away, so I will shut up now and show you some code I have built to do exactly this :)


 # Function generates uniq file name from the String passed to it
  # based on extension and basename
  #
  # @param [String] new_file_name desired file_name
  #
  # @return [String] generated file name
  def self.generate_random_filename(filename)
    ext = File.extname(filename)
    name = File.basename(filename, ext)
    related_file_indexes = []
    @file_list.select  do |file|
      if File.basename(file).include?(name) && File.extname(file) == ext
        related_file_indexes << file.split("-").last.to_i
      end
    end
    return name +  '-' + (related_file_indexes.max + 1).to_s + ext
  end

Short Explanation:

1. I take the file lets say ‘a.jpg’, and divide it into ‘a’ as a name and ‘.jpg’ as an extension.
2. I have a @file_list array that is pre-populated with filenames in the directory lets say @file_list is  [‘a-1.jpg’,’a-3.jpg’, ‘a.jpg’,’a-1.png’] .
3. I check if filename in @file_list consist of ‘a’ and with extension ‘.jpg’, thus I get 3 files [‘a-1.jpg’,’a.jpg’,’a-3.jpg’]
4. I have another array ‘related_file_indexes’, that splits every element of an array by last ‘-‘ and returns the number which gives me [‘1′,’3′]
5. I built filename with name, max of 1 and 3 which is 3+1=4 and append extension so my output will be ‘a-4.jpg

Full version of this code  with unit tests can be found here .

Once again, all suggestions and recommendation are more than welcome in the comments to this post ;)

Have a wonderful day!

Anatoly


Tagged: filename, files, open-source, Rspec, Ruby, unique file name

Viewing all articles
Browse latest Browse all 12

Trending Articles