Share this page

Learn X in Y minutes

Where X=ruby

# To jest komentarz

=begin 
To jest wielolinijkowy komentarz
Nikt ich nie używa
Ty też nie powinieneś
=end

# Przede wszystkim: Wszystko jest obiektem.

# Liczby są obiektami

3.class #=> Fixnum

3.to_s #=> "3"


# Trochę podstawowej arytmetyki
1 + 1 #=> 2
8 - 1 #=> 7
10 * 2 #=> 20
35 / 5 #=> 7
2**5 #=> 32
5 % 3 #=> 2
5 ^ 6 #=> 3

# Arytmetyka jest zastąpeniem składni
# metod wywoływanych na obiektach
1.+(3) #=> 4
10.* 5 #=> 50

# Wartości specjalne są obiektami
nil # To na prawdę jest niczym
true # prawda
false # fałsz

nil.class #=> NilClass
true.class #=> TrueClass
false.class #=> FalseClass

# Równość
1 == 1 #=> true
2 == 1 #=> false

# Nierówność
1 != 1 #=> false
2 != 1 #=> true

# jedyną 'fałszywą' wartością poza false, jest nil 

!nil   #=> true
!false #=> true
!0     #=> false

# Więcej porównań
1 < 10 #=> true
1 > 10 #=> false
2 <= 2 #=> true
2 >= 2 #=> true

# Operatory logiczne
true && false #=> false
true || false #=> true
!true #=> false

# Istnieją alternatywne wersje operatorów logicznych ze znacznie mniejszym
# pierwszeństwem. Używane są by kontrolować wyrażenia w łańcuchach wyrażeń
# aż jedno z nich wróci true lub false.

# `zrob_cos_innego` wywołaj tylko wtedy gdy `zrob_cos` zakończy się sukcesem.
zrob_cos_innego() and zrob_cos()
# `log_error` wywołaj tylko wtedy gdy `zrob_cos` nie zakończy się sukcesem.
zrob_cos() or log_error()


# Stringi są obiektami

'Jestem stringiem.'.class #=> String
"Ja również jestem stringiem.".class #=> String

wypelnienie = 'użyć interpolacji stringa'
"Potrafię #{wypelnienie} używając podwójnych cudzysłowów."
#=> "Potrafię użyć interpolacji stringa używając podwójnych cudzysłowów."

# Staraj się zapisywać stringi za pomocą apostrof, zamiast cudzysłowów tam, gdzie to możliwe
# Cudzysłowy wykonują dodatkowe wewnętrzne operacje


# Łączenie stringów, ale nie liczb
'hej ' + 'świecie'  #=> "hej świecie"
'hej ' + 3 #=> TypeError: can't convert Fixnum into String
'hej ' + 3.to_s #=> "hej 3"

# Łączenie stringów i operatorów
'hej ' * 3 #=> "hej hej hej "

# Dodawanie do stringa
'hej' << ' świecie' #=> "hej świecie"

# wydrukowanie wartości wraz z nową linią na końcu
puts "Drukuję!"
#=> Drukuję!
#=> nil

# wydrukowanie wartości bez nowej linii na końcu 
print "Drukuję!"
#=> Drukuję! => nill

# Zmienne
x = 25 #=> 25
x #=> 25

# Zauważ, że przypisanie zwraca przypisywaną wartość
# To znaczy, że możesz wykonać wielokrotne przypisanie:

x = y = 10 #=> 10
x #=> 10
y #=> 10

# Zwyczajowo, używaj notacji nazwa_zmiennej dla nazw zmiennych
nazwa_zmiennej = true

# Używaj opisowych nazw zmiennych
sciezka_do_projektu = '/dobra/nazwa/'
sciezka = '/zla/nazwa/'

# Symbole (są obiektami)
# Symbole są niezmiennymi, wielokrotnie używanymi stałymi reprezentowanymi wewnętrznie jako 
# liczby całkowite. Często używane są zamiast stringów w celu wydajniejszego przekazywania danych

:oczekujacy.class #=> Symbol

status = :oczekujacy

status == :oczekujacy #=> true

status == 'oczekujacy' #=> false

status == :zatwierdzony #=> false

# Tablice

# To jest tablica
array = [1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5]

# Tablice mogą zwierać różne typy danych

[1, 'hej', false] #=> [1, "hej", false]

# Tablice mogę być indeksowane
# Od początku
tablica[0] #=> 1
tablica.first #=> 1
tablica[12] #=> nil

# Podobnie jak przy arytmetyce, dostęp poprzez [zmienna]
# jest tylko czytelniejszą składnią
# dla wywoływania metody [] na obiekcie
tablica.[] 0 #=> 1
tablica.[] 12 #=> nil

# Od końca
tablica[-1] #=> 5
tablica.last #=> 5

# Z początkowym indeksem i długością
tablica[2, 3] #=> [3, 4, 5]

# Odwrotność tablicy
a=[1,2,3]
a.reverse! #=> [3,2,1]

# Lub zakres
array[1..3] #=> [2, 3, 4]

# Dodawanie do tablicy w taki sposób
tablica << 6 #=> [1, 2, 3, 4, 5, 6]
# Lub taki
tablica.push(6) #=> [1, 2, 3, 4, 5, 6]

# Sprawdzanie, czy tablica zawiera element
tablica.include?(1) #=> true

# Hasze są Ruby'owymi podstawowymi słownikami z parami klucz/wartość.
# Hasze są zapisywane za pomocą nawiasów klamrowych
hasz = { 'kolor' => 'zielony', 'numer' => 5 }

hasz.keys #=> ['kolor', 'numer']

# Można szybko sprawdzić zawartość hasza za pomocą kluczy:
hasz['kolor'] #=> 'zielony'
hasz['numer'] #=> 5

# Sprawdzenie wartośći dla nieistniejącego klucza zwraca nil:
hasz['nic tutaj nie ma'] #=> nil

# Od wersji 1.9, Ruby posiada specjalną składnię, gdy używamy symboli jako kluczy:

nowy_hasz = { stan: 3, akcja: true }

nowy_hasz.keys #=> [:stan, :akcja]

# Sprawdzenie istnienia kluczy i wartości w haszu
new_hash.has_key?(:defcon) #=> true
new_hash.has_value?(3) #=> true

# Wskazówka: Zarówno tablice, jak i hasze, są policzalne
# Współdzielą wiele metod takich jak each, map, count, i inne

# Instrukcje warunkowe

if true
  'wyrażenie if'
elsif false
  'wyrażenie if, opcjonalne'
else
  'wyrażenie else, również opcjonalne'
end

for licznik in 1..5
  puts "powtórzenie #{licznik}"
end
#=> powtórzenie 1
#=> powtórzenie 2
#=> powtórzenie 3
#=> powtórzenie 4
#=> powtórzenie 5

# JEDNAKŻE, Nikt nie używa pętli for.
# Zamiast tego, powinno się używać metody "each" i podawać jej blok.
# Blok jest kawałkiem kodu, który możesz podać metodzie podobnej do "each".
# Jest analogiczny do wyrażeń lambda, funkcji anonimowych lub zamknięć w innych
# językach programowania.
#
# Metoda "each" danego zakresu, wykonuje blok dla każdego elementu w zakresie.
# Do bloku zostaje przekazany licznik jako parametr.
# Wykonanie metody "each" z przekazaniem bloku wygląda następująco:

(1..5).each do |licznik|
  puts "powtórzenie #{licznik}"
end
#=> powtórzenie 1
#=> powtórzenie 2
#=> powtórzenie 3
#=> powtórzenie 4
#=> powtórzenie 5

# Możesz również otoczyć blok nawiasami klamrowymi:
(1..5).each { |licznik| puts "powtórzenie #{licznik}" }

# Zawartość struktur danych również może być powtarzana używając each.
tablica.each do |element|
  puts "#{element} jest częścią tablicy"
end
hasz.each do |klucz, wartosc|
  puts "#{klucz} jest #{wartosc}"
end

# Jeśli nadal potrzebujesz indeksum, możesz użyć "each_with_index" i zdefiniować 
# zmienną odpowiadającą indeksowi
tablica.each_with_index do |element, indeks|
  puts "#{element} jest numerem #{indeks} w tablicy"
end

licznik = 1
while licznik <= 5 do
  puts "powtórzenie #{licznik}"
  licznik += 1
end
#=> powtórzenie 1
#=> powtórzenie 2
#=> powtórzenie 3
#=> powtórzenie 4
#=> powtórzenie 5

# W Ruby istnieje dużo pomocnych funkcji wykonujących pętle,
# na przykład "map", "reduce", "inject" i wiele innych. Map,
# w każdym wywołaniu, pobiera tablicę, na której wykonuję pętlę,
# wykonuje kod zapisany za pomocą bloku i zwraca całkowicie nową tablicę.
tablica = [1,2,3,4,5]
podwojone = tablica.map do |element|
  element * 2
end
puts podwojona
#=> [2,4,6,8,10]
puts tablica
#=> [1,2,3,4,5]

ocena = 2

case ocena
when 1
  puts 'Dobra robota, masz wolne'
when 2
  puts 'Następnym razem będziesz miał więcej szczęścia'
when 3
  puts 'Możesz to zrobić lepiej'
when 4
  puts 'Przebrnąłeś'
when 5
  puts 'Oblałeś!'
else
  puts 'Inny system oceniania?'
end
#=> "Następnym razem będziesz miał więcej szczęścia"

# case może również użwać zakresów
ocena = 82
case ocena
when 90..100
  puts 'Hurra!'
when 80...90
  puts 'Dobra robota'
else
  puts 'Oblałeś!'
end
#=> "Dobra robota"

# obsługa błędów:
begin
  # kod, który może wywołać wyjątek
  raise NoMemoryError, 'Zabrakło pamięci.'
rescue NoMemoryError => zmienna_wyjatku
  puts 'Został wywołany NoMemoryError', zmienna_wyjatku
rescue RuntimeError => inna_zmienna_wyjatku
  puts 'Teraz został wywołany RuntimeError'
else
  puts 'To zostanie uruchomione, jeśli nie wystąpi żaden wyjątek'
ensure
  puts 'Ten kod wykona się zawsze'
end

# Funkcje

def podwojenie(x)
  x * 2
end

# Funkcje (i wszystkie bloki) zawsze zwracają wartość ostatniego wyrażenia
podwojenie(2) #=> 4

# Okrągłe nawiady są opcjonalne, gdy wynik jest jednoznaczny
podwojenie 3 #=> 6

podwojenie podwojenie 3 #=> 12

def suma(x, y)
  x + y
end

# Argumenty metod są oddzielone przecinkami
suma 3, 4 #=> 7

suma suma(3, 4), 5 #=> 12

# yield
# Wszystkie metody mają ukryty, opcjonalny parametr bloku,
# który może być wykonany używając słowa kluczowego 'yield'

def otoczenie
  puts '{'
  yield
  puts '}'
end

otoczenie { puts 'hej świecie' }

# {
# hej świecie
# }


# Możesz przekazać blok do funkcji
# "&" oznacza referencję to przekazanego bloku
def goscie(&blok)
  blok.call 'jakis_argument'
end

# Możesz przekazać listę argumentów, które będę przekonwertowane na tablicę
# Do tego służy operator ("*")
def goscie(*tablica)
  tablica.each { |gosc| puts gosc }
end

# Definiowanie klas używając słowa kluczowego class
class Czlowiek

  # Zmienna klasowa. Jest współdzielona przez wszystkie instancje tej klasy.
  @@gatunek = 'H. sapiens'

  # Podstawowe inicjalizowanie
  def initialize(imie, wiek = 0)
    # Przypisanie argumentu do zmiennej danej instancji o nazwie "imie"
    @imie = imie
    # Jeśli nie podano wieku, zostanie użyta domyślna wartość z listy argumentów.
    @wiek = wiek
  end

  # Podstawowa metoda przypisująca wartość
  def imie=(imie)
    @imie = imie
  end

  # Podstawowa metoda pobierająca wartość
  def imie
    @imie
  end

  # Powyższa funkcjonalność może być zastąpiona używając metody attr_accessor w taki sposób
  attr_accessor :imie

  # Metody przypisujące/pobierające mogą być stworzone indywidualnie
  attr_reader :imie
  attr_writer :imie

  # Metody klasowe używają self aby odróżnić się od metody instancji.
  # To może być wywołane na klasie, nie na instancji.
  def self.powiedz(wiadomosc)
    puts wiadomosc
  end

  def gatunek
    @@gatunek
  end
end


# Tworzenie instancji klasy
jim = Czlowiek.new('Jim Halpert')

dwight = Czlowiek.new('Dwight K. Schrute')

# Wywołajmy parę metod
jim.gatunek #=> "H. sapiens"
jim.imie #=> "Jim Halpert"
jim.imie = "Jim Halpert II" #=> "Jim Halpert II"
jim.imie #=> "Jim Halpert II"
dwight.gatunek #=> "H. sapiens"
dwight.imie #=> "Dwight K. Schrute"

# Wywołanie metody klasowej
Czlowiek.powiedz('Cześć') #=> "Cześć"

# Zasięg zmiennej jest definiowany poprzez jej nazwę.
# Zmienne, które zaczynają się na $ mają zasięg globalny
$zmienna = "Jestem zmienną globalną"
defined? $zmienna #=> "global-variable"

# Zmienne zczynające się na @ mają zasięg danej instancji
@zmienna = "Jestem zmienną instancji"
defined? @zmienna #=> "instance-variable"

# Zmienne, które zaczynają się na @@ mają zasięg danej klasy
@@zmienna = "Jestem zmienną klasową"
defined? @@zmienna #=> "class variable"

# Zmienne, które zaczynają się na dużą literę, są stałymi
Zmienna = "Jestem stałą"
defined? Zmienna #=> "constant"

# Klasa jest również obiektem w ruby. Może więc mieć zmienne instancji.
# Zmienna klasowa może być współdzielona między klasą i jej potomstwem.

# podstawowa klasa
class Czlowiek
  @@cokolwiek = 0

  def self.cokolwiek
    @@cokolwiek
  end

  def self.cokolwiek=(wartosc)
    @@cokolwiek = wartosc
  end
end

# klasa pochodna
class Pracownik < Czlowiek
end

Czlowiek.cokolwiek # 0
Pracownik.cokolwiek # 0

Czlowiek.cokolwiek = 2 # 2
Pracownik.cokolwiek # 2

# Zmienna instancji danej klasy nie jest współdzielona przez jej potomstwo.

class Czlowiek
  @cos = 0

  def self.cos
    @cos
  end

  def self.cos=(wartosc)
    @cos = wartosc
  end
end

class Doktor < Czlowiek
end

Czlowiek.cos # 0
Doktor.cos # nil

module PrzykladowyModul
  def cokolwiek
    'cokolwiek'
  end
end

# Włączanie modułów łączy ich metody z metodami instancji klasy
# Rozszerzanie modułów łączy ich metody z metodami klasy

class Osoba
  include PrzykladowyModul
end

class Ksiazka
  extend PrzykladowyModul
end

Osoba.cokolwiek         # => NoMethodError: undefined method `cokolwiek' for Osoba:Class
Osoba.new.cokolwiek     # => 'cokolwiek'
Ksiazka.cokolwiek       # => 'cokolwiek'
Ksiazka.new.cokolwiek   # => NoMethodError: undefined method `cokolwiek'

# Gdy włączamy lub rozszerzamy muduły, wykonywane są tzw. wywołania zwrotne

module PrzykladowyModul
  def self.included(baza)
    baza.extend(MotodyKlasowe)
    baza.send(:include, MetodyInstancji)
  end

  module MotodyKlasowe
    def cos
      'cos'
    end
  end

  module MetodyInstancji
    def xyz
      'xyz'
    end
  end
end

class Cokolwiek
  include PrzykladowyModul
end

Cokolwiek.cos     # => 'cos'
Cokolwiek.xyz     # => NoMethodError: undefined method `xyz'
Cokolwiek.new.cos # => NoMethodError: undefined method `cos'
Cokolwiek.new.xyz # => 'qux'

Dodatkowe źródła

Polskie

Angielskie


Got a suggestion? A correction, perhaps? Open an Issue on the Github Repo, or make a pull request yourself!

Originally contributed by David Underwood, and updated by 10 contributor(s).