Since you asked for user ids, I'm going to assume
There should be no collisions in the user ids.
Because of this, you don't want just purely random ids, otherwise you'll end up with a collision as a result of the birthday problem. Out of only 10^8 random userids, this means the odds are significant that a collision will occur after around 10^4 users, and it is always possible it may happen earlier than this.
What you are looking for is a permutation function. Using some basic number theory, here's one simple, non-secure way to do it:
N = 99999999 # set of ordered numbers to permute = {0,1,2,...,N-1}
P = 1000000007 # prime number larger than N
A = 181932213 # random integer: 2 <= A < P
B = 611232645 # random integer: 0 <= B < P
def get_user_id( i )
j = i.instance_of?(Fixnum) ? i : i.dup # i.dup if i is a Bignum
j -= 1
begin j = ( A * j + B ).modulo P end until j < N
j + 1
end
Internally, you still want to generate incremental ids id
. Then get_user_id(id)
with return an 8-digit number (or less) which you can use as the user_id
, which is guaranteed to not conflict with any other user_id
for all non-zero 8-digit numbers id
.
To illustrate:
1.upto(N) do |i|
j = get_user_id(i)
puts "#{i}\t#{j}"
end
Output:
1 41168842
2 45894710
3 11122313
4 74043578
5 78434518
6 72415977
...
Note that anyone who knows/suspects you are using this algorithm can fairly easily determine what N, P, A, and B are from getting some consecutively generated values, and obtain the underlying id
value which you wanted to keep hidden. If you need something more secure than this, then consider looking into permutation ciphers.