2010-01-02 6 views
2

J'utilise MongoDB comme backend pour une application Rails que je construis. Mongo, par défaut, génère 24 caractères hexadécimaux ids pour ses enregistrements pour rendre plus facile sharding, donc mes URL vent ressembler:Compression d'une chaîne hexadécimale dans Ruby/Rails

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

Ce qui est pas très jolie. Je tiens à respecter les conventions url Rails, mais aussi laisser ces identifiants tels qu'ils sont dans la base de données. Je pense qu'un heureux compromis serait de compresser ces ids hexagonaux à des collections plus courtes en utilisant plus de caractères, de sorte qu'ils chercherais quelque chose comme:

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

Puis, dans mon contrôleur j'inverser la compression, obtenir l'ID hexadécimal d'origine et l'utiliser pour rechercher le disque.

Ma question est, quelle est la meilleure façon de convertir ces id et-vient? Je voudrais bien sûr qu'ils soient aussi courts que possible, mais aussi sûrs d'url et simples à convertir.

Merci!

Répondre

5

Vous pouvez représenter un identifiant hexadécimal dans une base supérieure à 16 pour rendre sa représentation de chaîne plus courte. Ruby a un support intégré pour travailler avec des bases de 2 jusqu'à 36.

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

pour le convertir en une chaîne de 24 caractères que vous pourriez faire quelque chose comme ceci:

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

Pour obtenir une meilleure « compression », vous pouvez représenter l'identifiant dans la base supérieure à 36. Il y a des bibliothèques Ruby qui vous aideront avec ça. Gem est une telle bibliothèque.

Je recommande la représentation de base 62 car il utilise seulement 0-9, a-z et A-Z caractères qui signifie qu'il est sûr URL par défaut.

0

Vous pouvez utiliser base64 pour le raccourcir. Assurez-vous que vous utilisez '-' et '_' au lieu de '+' et '/'. Vous pouvez également couper du rembourrage =.

code

convertir une valeur hexadécimale à la 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 
+0

Comment est-ce que je ferais ceci? J'ai essayé d'utiliser Base64.encode64 sur les identifiants de chaîne, mais cela les rend plus longs. – PreciousBodilyFluids

+0

Cet extrait montre comment cela peut être fait http://rubyforge.org/snippet/detail.php?type=snippet&id=33 –

+2

Base64.encode64 rend les identifiants plus longs car vous les utilisez en tant que chaînes au lieu de données binaires. – epochwolf

1

Même avec la base 62 représentation vous vous retrouvez avec 16 caractères encore difficiles à manier ids:

'4b3fc1400de0690bf2000001'.hex.to_base_62 
# => "UHpdfMzq7jKLcvyr" 

convention esquives Rails un peu, un autre compromis est d'utiliser comme base 32 représentation « id URL » du created_at date de l'objet.

aCompany.created_at 
# => Sat Aug 13 20:05:35 -0500 2011 
aCompany.created_at.to_i.to_s(32) 
# => "174e7qv" 

De cette façon, vous obtenez super court ids (7 caractères) sans avoir à garder la trace d'un attribut spécial (en MongoMapper, il est une simple question d'ajouter timestamps! dans le modèle pour obtenir les attributs automatiques created_at et updated_at) .

Questions connexes