If you work in web development, you’ve almost certainly had to generate random numeric codes like OTPs for logins or transaction verifications sent via SMS or email.
It seems like a straightforward task, and your first instinct might be to reach for Kernel#rand. But that method isn’t designed for cryptographically secure random numbers, so the documentation advises switching to a safer alternative: SecureRandom#rand.
Next comes requirements that can vary depending on the use case: do all ten digits need to be included in the code, do you need to exclude certain numbers, or do you need to mix in alphanumeric characters.
require 'securerandom'
# fast, but unsafe
rand(0..9999).to_s.rjust(4, '0')
Array.new(4) { rand(10) }.join
# more reliable for the entire range of digits
SecureRandom.rand(0..9999).to_s.rjust(4, '0')
Array.new(4) { SecureRandom.rand(0..9) }.join
# without digits: 0, 1, 5, 6
chars = %w[2 3 4 7 8 9]
SecureRandom.alphanumeric(4, chars:)
Array.new(4) { chars[SecureRandom.rand(chars.length)] }.join
chars.sample(4, random: SecureRandom).join
# explicitly make a system call to the OS
`head -c 4 /dev/random`.bytes.map { _1 % 10 }.join
How do you generate random codes in your projects? Are there other ways you like to handle this cleanly?