2011-05-06 20 views
5

Necesito generar un código alfanumérico de seis dígitos único. Para guardar en mi base de datos como no voucher: para cada transacción.Cómo generar un código alfanumérico único de seis dígitos en Ruby

+2

¿Por qué no solo está autoincrementando el código? Serían numéricos entonces. Si tiene demasiados códigos (más de 6 dígitos), puede usar una base32 de este número, p. – Jens

+0

¿Posible duplicado? http://stackoverflow.com/questions/88311/how-best-to-generate-a-random-string-in-ruby – Teoulas

+0

@Teoulas No lo creo. No hay nada en esta pregunta que indique que los códigos deben ser (o aparecer) aleatorios. – Phrogz

Respuesta

3

I utilizó este

require 'sha1' 
    srand 
    seed = "--#{rand(10000)}--#{Time.now}--" 
    Digest::SHA1.hexdigest(seed)[0,6] 

How to generate a random string in Ruby este enlace fue útil

+1

Esta es una respuesta muy mala con alta probabilidad de colisión. Con 1 millón de iteraciones hay 767 ** mil ** colisiones en 215 mil claves. Alterar el número aleatorio de '10000' a' 10000000' reduce las colisiones a "solo" 31,000 de 1,000,000, pero cualquier colisión sigue siendo mala. Esto es cierto tanto si Time.now es siempre el mismo como si devuelve un nuevo valor en cada llamada (por ejemplo, no más de una transacción por segundo). – Phrogz

+0

En el caso normal este es aceptable. ¿Hay alguna otra manera para esto? – rubyprince

0

Una mejor manera es dejar que la base de datos maneje los identificadores (incrementando). Pero si insiste en generarlos usted mismo, puede usar un generador aleatorio para generar un código, compruébelo con db para ver su singularidad. entonces aceptar o regenerar

+0

Esta es una mala idea en teoría cuando empiezas a llenar el espacio de nombres disponible, ya que aumentan tus posibilidades de colisiones y, en el extremo, puedes terminar atrapado en un ciclo de regeneración durante mucho tiempo antes de encontrar una clave libre. – Phrogz

0

que haría uso de la base de datos para generar claves únicas, pero si insiste en hacerlo de la manera difícil:

class AlnumKey 

    def initialize 
    @chars = ('0' .. '9').to_a + ('a' .. 'z').to_a 
    end 

    def to_int(key) 
    i = 0 
    key.each_char do |ch| 
     i = i * @chars.length + @chars.index(ch) 
    end 
    i 
    end 

    def to_key(i) 
    s = "" 
    while i > 0 
     s += @chars[i % @chars.length] 
     i /= @chars.length 
    end 
    s.reverse 
    end 

    def next_key(last_key) 
    to_key(to_int(last_key) + 1) 
    end 
end 

al = AlnumKey.new 
puts al.next_key("ab") 
puts al.next_key("1") 
puts al.next_key("zz") 

Por supuesto, usted tiene que almacenar su clave actual en algún lugar, y esto es en ningún hilo forma/multisesión-safe etc.

0

con las siguientes restricciones:

  1. válido sólo hasta el 24/12/2038 00:40:35 GMT
  2. no genera más de una vez dentro de un segundo

puede utilizar este sencillo código:

Time.now.to_i.to_s(36) 
# => "lks3bn" 
+2

¿Qué pasará si se cambia la hora del sistema? – Zabba

+0

a la vez Necesito obtener diferentes identificadores de cupones –

+0

@Zabba Eso causará un problema, pero asumí que no será tan frecuente. En ese caso, el sistema tendrá que estar inactivo para el mantenimiento durante el lapso de tiempo que iguala la diferencia entre las zonas horarias nueva y antigua. Será menos de un día, en el peor. Si la nueva zona horaria continúa, el sistema no tiene que estar inactivo. – sawa

0
class IDSequence 
    attr_reader :current 
    def initialize(start=0,digits=6,base=36) 
    @id, @chars, @base = start, digits, base 
    end 
    def next 
    s = (@id+=1).to_s(@base) 
    @current = "0"*(@chars-s.length) << s 
    end 
end 

id = IDSequence.new 
1234.times{ id.next } 

puts id.current 
#=> 0000ya 

puts id.next 
#=> 0000yb 

9876543.times{ id.next } 
puts id.current 
#=> 05vpqq 
0

Esto eleviat e el problema de la colisión de tiempo al obtener los mili segundos

(Time.now.to_f*1000.0).to_i 
Cuestiones relacionadas