Spread Operator w Ruby i Ruby Ranges

Wszyscy pamiętamy jak rewolucyjne w świecie JavaScriptu okazało sie wprowadzenie tzw. <strong>spread operator</strong> wraz ze standardem ES6. Praca z kolekcjami stała się prosta i przyjemna. Łączenie tablic stało się banalne. Można pomyśleć, że to sprawia, że JS jest pod tym względem wyjątkowy…ale nie. Używaliśmy spread operator w Ruby, zanim to stało się modne. Zatem, jeśli chcesz poznać, czym jak wygląda spread operator w Ruby i Ruby Ranges (bardzo ciekawy obiekt), to zapraszam do lektury.

Z mojego doświadczenia Ruby to język, który ma szeroko rozwinięte API jeśli chodzi o operacje wykonywane na kolekcjach. Wszystko dzięki modułowi <strong>Enumerable</strong> i klasie <strong>Array</strong>, które dostarczają wszystkich ciekawych funkcjonalności.

Concat

I tak Ruby posiada metodę <strong>concat</strong>, która służy do łączenia tablic ze sobą, czyli do, akcji, którą bardzo często wykorzystuje się w JS.

[1, 2].concat(['a', 'b']) #=> [1, 2, 'a', 'b']

Magia Ruby

Pozwól, że pokażę Ci przykład, jakim świetnym językiem jest Ruby. Wykorzystam do tego kilka mniej oczywistych metod tablicowych i inne fajne narzędzie, jakim są Ruby Ranges.

Fake password generator

Napiszmy sobie prosty generator haseł, który możemy wykorzystać do seedowania bazy, mockowania danych testowych albo wygenerowania tymczasowego hasła dla użytkownika.

Wymagania biznesowe:

  • hasło może zawierać małe litery
  • hasło może zawierać duże litery
  • hasło może zawierać cyfry
  • hasło może zawierać znaki specjalne: $, #, *
  • hasło może zawierać losowo wygenerowane słowo z języka Wookie, wykorzystamy gem Faker

Jedziemy!

Hasło może zawierać małe litery

Nie trzeba nic instalować, wykorzystamy obiekt Range, który pozwala na wygenerowanie zbioru znaków lub liczb z określonego zakresu. Następnie skonwertujemy ten obiekt na tablicę metodą to_a.

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"]

Hasło może zawierać duże litery

Też wykorzystamy Range. Wystarczy zmienić tylko parametry na duże znaki.

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"]

Hasło może zawierać cyfry

I znowu Range.

numbers = (0..9).to_a

#=>
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Hasło może zawierać znaki specjalne: $, #, *

Tutaj wystarczy prosta tablica

special_characters = ['$', '#', '*']

Łatwo zrobić literówkę i zapomnieć apostrofa, skorzystajmy z bardziej fancy składni.

special_characters = %w{ $ # * }

#=>
['$', '#', '*']

Hasło może zawierać losowo wygenerowane słowo z języka Wookie

Wygląda na najtrudniejszą część, co nie?

wookie_words = Faker::Movies::StarWars.wookiee_sentence.split

#=>
["Ru", "ooma", "nng", "roooarrgh", "roooarrgh!"]

Posiłkuję się metodą split, która, jako separator domyślny przyjmuje spację i rozbija mi wygenerowane zdanie na tablicę słów zrozumiałych dla Chewbacci.

Generowanie hasła

Skoro mamy już części składowe pora na wygenerowanie hasła. Poskładajmy najpierw wszystkie kryteria w jedną tablicę.

password_matrix = lowercase_letters
			          .concat(capital_letters)
				        .concat(numbers)
				        .concat(special_characters)
				        .concat(wookie_words)

Shuffle

Zamieszajmy z bang method.

password_matrix.shuffle!

Sample

Wybierzmy 20 losowych elementów i znów zamieszajmy.

password_matrix = password_matrix.sample(20).shuffle

Join

Teraz łączymy i mamy gotowe hasło.

password_matrix.join

#=>
"r4gP#Tsga.0aBbKc$kabukkmCYhnn-rowr"

Spread Operator

Cały kod, z małym refactorem upraszczającym kroki wygląda tak:

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

Dużo tego kodu, no i obiecałem Ci spread operator. Otóż, aby połączyć tablice w jedną wystarczy znak *.

password_matrix = [ *lowercase_letters, *capital_letters, *numbers, *special_characters, *wookie_words]

Końcowy kod wygląda tak:

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

I działa jak złoto!

Na pewno zainteresuje Cię, co to jest definition spec i jakie daje korzyści.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

You May Also Like
Czytaj

Simple Command

Kto kiedykolwiek pracował w projekcie railsowym napewno widział tzw. fat controllers, gdzie logika poszczególnych akcji wpakowana jest bezpośrednio w…
Czytaj

Ruby Mixins – Include

Ruby jak każdy język obiektowy opiera się na dziedziczeniu. Ze względu na ograniczenie, w postaci dziedziczenia na raz…
Czytaj

Ruby Mixins – Prepend

Ruby jak każdy język obiektowy opiera się na dziedziczeniu. Ze względu na ograniczenie, w postaci dziedziczenia na raz…
Czytaj

Range i Date w Ruby on Rails

W jednym z poprzednich postów pokazywałem przykład zastosowania obiektu Range w Ruby. Ruby on Rails posiada własne rozszerzenie klasy…
Czytaj

Ruby Mixins – Extend

Ruby jak każdy język obiektowy opiera się na dziedziczeniu. Ze względu na ograniczenie, w postaci dziedziczenia na raz…