Вопрос

For example: If I'm creating a new user in Rails, the id number will be 1, 2, 3 and so on. In the URL the users id will be like "users/1". My question is: How do I make a random number for every new users? So the id won't be 1, 2, 3 and so on. More like id: 643893, name: Carl, age: 34?

Это было полезно?

Решение

If you really insist upon the digits, you could do something like this

def random_id
  Random.new.bytes(8).bytes.join[0,8]
end

5.times { puts random_id }

Output

19854517
11802301
16391219
18414719
35583913

Anyway, I believe you have a bit of an XY Problem and your end goal is to just generate unique ids for your users. The function above is going to be random but without checking with your database, you'll have no idea whether the result is unique or not. Here's some alternative approaches I'd take:

If you wanted, it's not 8 digits, but you could slice of the beginning of a uuid

require "securerandom"

SecureRandom.uuid.split("-").first
# b05582d8

That said, I think it's a much better to use the whole thing

SecureRandom.uuid
# b05582d8-3489-4bba-b94f-565ee458b1f9

Другие советы

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.

Below is the example, which start with alphabet.

def self.generate_reg_no
  @reg_no = PatientReg.last
  @reg_no.blank? ? (@reg_no = 'REG00') : (@reg_no = @reg_no.reg_no)     
  new_id =""
  n = @reg_no.length
  last_count = @reg_no.slice!(4..n)
  new_id << "REG0" << (last_count.to_i+1).to_s
end 

You can modify as per you requirement.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top