views:

390

answers:

2

I'm using MongoDB as a backend for a Rails app I'm building. Mongo, by default, generates 24-character hexadecimal ids for its records to make sharding easier, so my URLs wind up looking like:

example.com/companies/4b3fc1400de0690bf2000001/employees/4b3ea6e30de0691552000001

Which is not very pretty. I'd like to stick to the Rails url conventions, but also leave these ids as they are in the database. I think a happy compromise would be to compress these hex ids to shorter collections using more characters, so they'd look something like:

example.com/companies/3ewqkvr5nj/employees/9srbsjlb2r

Then in my controller I'd reverse the compression, get the original hex id and use that to look up the record.

My question is, what's the best way to convert these ids back and forth? I'd of course want them to be as short as possible, but also url-safe and simple to convert.

Thanks!

A: 

You can use base64 to make it shorter. Make sure that you are using '-' and '_' instead of '+' and '/'. You can also chop of the padding =.

Code to convert from a hex value to base 64

def MD5hex2base64(str)
  h1=[].clear

  # split the 32 byte hex into a 16 byte array
  16.times{ h1.push(str.slice!(0,2).hex) }
  # pack (C* = unsigned char), (m = base64 encoded output)
  [h1.pack("C*")].pack("m")
end
NA
How would I do this? I've tried using Base64.encode64 on the string ids, but that just makes them longer.
PreciousBodilyFluids
NA
Base64.encode64 makes the ids longer because you are using them as strings instead of binary data.
epochwolf
+1  A: 

You could represent a hexadecimal id in a base higher than 16 to make its string representation shorter. Ruby has built-in support for working with bases from 2 up to 36.

b36 = '4b3fc1400de0690bf2000001'.hex.to_s(36)
# => "29a6dblglcujcoeboqp"

To convert it back to a 24-character string you could do something like this:

'%024x' % b36.to_i(36)
# => "4b3fc1400de0690bf2000001"

To achieve better "compression" you could represent the id in base higher than 36. There are Ruby libraries that will help you with that. all-your-base gem is one such library.

I recommend base 62 representation as it only uses 0-9, a-z and A-Z characters which means it is URL safe by default.

mtyaka