Spread Operator in Ruby and Ruby Ranges
Rafał Piekara
Posted on January 30, 2022
We all remember the revolutionary in JavaScript world turned out to be the introduction of spread operator
with the ES6 standard. Working with the collection has become pleasant and easy. Joining arrays has become very simple. You might think that this makes JS unique in this regard… but no. We used the spread operator in Ruby before it became fashionable. So, if you want to know what the spread operator in Ruby and Ruby Ranges looks like (a very interesting object), I invite you to read it.
I've learned from experience that Ruby language has a well-developed API when it comes to operations on collections. All thanks to the Enumerable
module and the Array
class, which provide all interesting functionalities.
Concat
And so Ruby has a concat
method that is used to join arrays together, so, to actions very often used in JS.
[1, 2].concat(['a', 'b']) #=> [1, 2, 'a', 'b']
Ruby Magic
Let me show you an example that proves how great a language Ruby is. We'll use a few less obvious array methods and another cool tool such as Ruby Ranges.
Fake password generator
Let's write a simple password generator that we can use to seed the database, mock test data, or generate a password for the user.
Business requirements:
the password may contain lowercase letters
password may contain uppercase letters
the password may contain numbers
the password may contain special characters: $, #, *
the password may contain a randomly generated Wookie word, we will use the Faker gem
Let’s do this!
The password may contain lowercase letters
You don't need to install anything, we will use the Range
object which allows us to generate a set of characters or numbers from a specified range. Then we'll convert this object to an array using the to_a
method.
lowercase_letters = ('a'..'z').to_a
#=>
["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
The password may contain uppercase letters
Here we will also use Range
all we need to do is to change parameters to uppercase.
capital_letters = ('A'..'Z').to_a
#=>
["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
The password may contain numbers
And Range
again.
numbers = (0..9).to_a
#=>
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
The password may contain special characters: $, #, *
A simple board is enough here
special_characters = ['$', '#', '*']
It's easy to make a typo and forget the apostrophe, let's use more fancy syntax.
special_characters = %w{ $ # * }
#=>
['$', '#', '*']
The password may contain a randomly generated Wookie word
Seems like the hardest part, right?
wookie_words = Faker::Movies::StarWars.wookiee_sentence.split
#=>
["Ru", "ooma", "nng", "roooarrgh", "roooarrgh!"]
I use the split
method, which takes space as a default separator and breaks the generated sentence into an array of words understood by Chewbacci.
Password generation
Now we have the components, it's time to create a password. First, let's sort all the criteria into one array.
password_matrix = lowercase_letters
.concat(capital_letters)
.concat(numbers)
.concat(special_characters)
.concat(wookie_words)
Shuffle
Let's mix it up with the bang method.
password_matrix.shuffle!
Sample
Let's pick 20 random pieces and mix it up again.
password_matrix = password_matrix.sample(20).shuffle
Join
Now we have to connect and we have the password ready.
password_matrix.join
#=>
"r4gP#Tsga.0aBbKc$kabukkmCYhnn-rowr"
Spread Operator
All the code, with a small, refactor to simplify the steps, looks like this:
def fake_password
lowercase_letters = ('a'..'z').to_a
capital_letters = ('A'..'Z').to_a
numbers = (0..9).to_a
special_characters = %w{ $ # * }
wookie_words = Faker::Movies::StarWars.wookiee_sentence.split
password_matrix = lowercase_letters
.concat(capital_letters)
.concat(capital_letters)
.concat(numbers)
.concat(special_characters)
.concat(wookie_words)
.shuffle
.sample(20)
.shuffle
.join
end
A lot of this code, and I promised you a spread operator. Well, to combine arrays into one, all you need is *
.
password_matrix = [ *lowercase_letters, *capital_letters, *numbers, *special_characters, *wookie_words]
Final code looks like that:
def fake_password
lowercase_letters = ('a'..'z').to_a
capital_letters = ('A'..'Z').to_a
numbers = (0..9).to_a
special_characters = %w{ $ # * }
wookie_words = Faker::Movies::StarWars.wookiee_sentence.split
password_matrix = [lowercase_letters, capital_letters, numbers, special_characters, *wookie_words]
password_matrix
.shuffle
.sample(20)
.shuffle
.join
end
It work a treat!
Posted on January 30, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.