How to Generate Random Numbers & Strings in Ruby

If you want to learn how to generate random numbers & strings in Ruby, then you’re in the right place.

Because that’s exactly what this article is about!

With a random number you can pick a random element from an array, pick a winner from a list, generate dice rolls, etc.

In Ruby, there are many ways to generate random numbers with various properties.

For example…

The rand method can be used in 3 ways:

  • Without arguments, rand gives you a floating point number between 0 & 1 (like 0.4836732493)
  • With an integer argument (rand(10)) you get a new integer between 0 & that number
  • With a range argument (rand(1..20)) you get an integer between the start of the range & the end of the range

Other ways to generate randomness in Ruby include:

  • The Array#shuffle method
  • The Array#sample method
  • The SecureRandom class

Let’s go over some examples!

Generating Random Numbers

You can generate Ruby random numbers using the rand method:

ruby random

Rand produces floating point numbers (0.4836732493) if called without any arguments.

You can pass an argument to rand to generate a number starting from zero up to (but not including) that number.

rand 100
> 41

Ruby random number generation is really easy, but what if you need the number to be in a specific range instead of starting from zero?

Not a problem!

You can use a range to get exactly what you need.

Example:

rand 200..500
> 352

Secure Ruby Random Numbers

The numbers produced by rand might be enough for a simple application…

…but if you want to use them for security purposes —like generating a password reset token— then you should use SecureRandom, which is part of the Ruby standard library.

SecureRandom seeds its generator from /dev/urandom on Unix systems & on windows it uses the CryptAcquireContext / CryptGenRandom API.

Here’s an example:

require 'securerandom'

SecureRandom.random_number
> 0.232

As you can see this works a lot like rand, you can also pass in a max number.

Example:

SecureRandom.random_number(100)
> 72

SecureRandom has other output formats available.

Using hex can generate a hexadecimal fixed-width string.

SecureRandom.hex
> "87694e9e5231abca6de39c58cdfbe307"

Ruby 2.5 introduced a new method, which produces random alphanumeric strings:

SecureRandom.alphanumeric
> "PSNVXOeDpnFikJPC"

How to Pick Random Elements From Arrays

Now:

You may want to get a random pick from a list.

You can try this:

[5, 15, 30, 60].shuffle.first
> 30

But Ruby has the sample method which is better suited (and faster) for this task:

[5, 15, 30, 60].sample
> 5

You can use sample for ranges, this code generates a random letter:

('a'..'z').to_a.sample
> b

You can pass an integer argument to sample to get N unique elements from the array:

[1,2,3].sample(2)
> [1, 2]

It’s also possible to pass a custom random generator as an argument:

[1,2,3].sample(random: SecureRandom)

Ruby Random Strings

The ultimate randomness application is to generate a random string with a custom character set. Here is the code:

def generate_code(number)
  charset = Array('A'..'Z') + Array('a'..'z')
  Array.new(number) { charset.sample }.join
end

puts generate_code(20)

There are a few things going on here.

First, we prepare our charset using ranges and converting them to arrays. Then we take advantage of calling Array.new with a block, which lets us initialize an array of size n with the values produced by the block.

This code will produce strings of the following form: TufwGfXZskHlPcYrLNKg.

You can tweak the character set to fit your needs.

Seeding The Random Number Generator

If you would like to control what numbers are generated when using a method like rand then you can set the seed.

What is the seed?

The seed is a number that starts a sequence of random numbers.

All generated numbers are derived from this seed.

That’s why the quality of the seed is usually the key to producing a good sequence of random numbers.

Ruby already takes care of that for you (use SecureRandom if you need extra security), but in some scenarios (mostly testing & debugging) you may want to set this seed yourself.

You can do this with the srand method.

Like this:

Kernel.srand(1)

With this seed you’ll know exactly what numbers the generator is going to give you.

For the number 1 as the seed:

Array.new(5) { rand(1..10) }
# [6, 9, 10, 6, 1]

If you set the seed again to 1, the sequence will start at 6, then 9, 10, etc.

Conclusion

That’s it! You are now ready to start using randomness in your Ruby programs 🙂

Found this post useful?

Share it with your friends & subscribe to my newsletter so you don’t miss anything new!

8 thoughts on “How to Generate Random Numbers & Strings in Ruby”

  1. You can pass an argument to sample for the number of elements you want back, so you can simplify this:

    Array.new(number) { charset.sample }.join

    to

    charset.sample(number).join

    You can also splat ranges, so you could create one array instead of two; e.g.

    charset = [*"a".."z", *"A".."Z"]

    Assuming that method is going to be called more than once, it would make sense to define it once as a constant (or possibly class variable) outside of the routine, rather than generating it each call, so more like:

    CHARSET = [*"a".."z", *"A".."Z"]
    def generate_code(number); CHARSET.sample(number).join

    • Thank you, I didn’t know that you can pass an argument to sample. And I agree that you should only generate the charset once if you are going to use the method multiple times, but I didn’t want to make the code more complex for the examples.

      • This is not true actually. `sample` with arguments generates sample without repetitions, so it’s totally different from the original code!

        • You are right! Thanks for letting us know 🙂

          For reference, this is what the documentation has to say about sample:

          The elements are chosen by using random and unique indices into the array in order to ensure that an element doesn’t repeat itself unless the array already contained duplicate elements.

          In fact, if you do this:
          charset = [*'a'..'z', *'A'..'Z'].sample(100).join.size

          You only get 52 (one for each in the character set), which might not be what you want.

    • One of the many things I like about Ruby is how it seems every day I get a chance to learn something new about the language. I had never seen that splat do on a range before.

      The other thing I learned today is that coping code that has smart quotes in it gets a syntax error.

  2. o = [('a'..'z'), ('A'..'Z')].map { |i| i.to_a }.flatten
    string = (0...50).map { o[rand(o.length)] }.join

    From Stack Overflow works fine.

    I used a variant in one of my scripts works awesomely well and it’s fast. That said, it’s way better to write code you and others can understand on the fly in production mode, than smart-ass long snippets copy-pasted from SO.

    I think creating a method (like a black box) is the way to go.

Comments are closed.