2

I want to create a model that has a attribute that holds a string based unique identifier.

I only want the unique string to be 3 characters long and consist of letters of the alphabet (lower case only) and numbers.

How do I implement something like the above? How do I avoid collisions? I have looked into MD5, and that seems along the lines of what I want to accomplish - but shorter. I am willing to also seed it with a time if that make the approach deterministic.

I would love any feedback or pointers on this topic. Thanks!

EDIT: One solution that has been on my mind is creating a table full of every single permutation, then randomly selecting as needed from the table, and deleting once used. Is this a bad approach?

aren55555
  • 1,677
  • 1
  • 20
  • 34
  • 3 characters seems a bit optimistic. Why do you need it to be so short, and only alphabetical? – Jeremy Rodi Aug 29 '12 at 03:02
  • This only works if you expect to never have more than 46656 records in your database. Also, do you want the identifiers to be generated randomly, or can you simply start with 'aaa', 'aab', 'aac'... – user229044 Aug 29 '12 at 03:04
  • Well I figure I start with 3 characters and bump it up as needed. The user needs to use these characters in a mailing address, so shorter is better. The identities should not be predictable, but rather random. – aren55555 Aug 29 '12 at 03:08
  • Right now I am thinking about writing a Ruby script to generate every 3 character permutation and store in a table. Then I'll just go pluck and delete as needed. Is this a bad idea? – aren55555 Aug 29 '12 at 03:09
  • @aren55555: Yes, if you intend to have any security. There aren't that many permutations we're talking about here. Your key size is just to small to be usable for unique identifiers. Rethink your idea. – Linuxios Aug 29 '12 at 05:44
  • I have to keep it short because the generated string is essentially being used like a postal code. I decided to just generate tables full of every combination. I randomly pick unused entries and use them. This method allows me to have the short strings and no collisions ever. – aren55555 Aug 29 '12 at 05:56

3 Answers3

1

Check out this SO thread; it's got plenty of good suggestions. Especially the last answer by Simone Carletti which points to this post.

There are quite a few options on the above post. The one I liked and might be useful for you is the use of rufus-mnemo gem

Community
  • 1
  • 1
rb512
  • 6,880
  • 3
  • 36
  • 55
  • I saw that post, however the solution: `rand(36**8).to_s(36)` kind of concerns me with collisions. – aren55555 Aug 29 '12 at 03:10
  • As @meagar pointed out, your size limit for the UID is too thin and you'll 've to employ some mechanism to check for collision (eg: generate a key and check if it already exists). If you wish to avoid that broaden the size limit. – rb512 Aug 29 '12 at 03:18
0

So the solution I decided to roll with after reading some of the questions & answers is quite different than what anyone had suggested.

I created a table to store codes. I wrote a ruby script to populate this table with every 3 letter combo based on the characters I wanted to use. Then on my model I have a before_save method assign a code to the instance if a code has not yet been assigned.

This approach ensures that I will never have a collision when assigning a code in the before_save. The slowest part is the generation of the table, but since I only have to do this once I can deal with this.

aren55555
  • 1,677
  • 1
  • 20
  • 34
0

This gem called alphadecimal might be able to help you.

Pedro Nascimento
  • 13,136
  • 4
  • 36
  • 64