Programowanie w jezyku Rubypolak/wyklady/jezyki/ruby.pdf · 2020-04-17 · 4 dane2=readlines() 5...
Transcript of Programowanie w jezyku Rubypolak/wyklady/jezyki/ruby.pdf · 2020-04-17 · 4 dane2=readlines() 5...
Programowanie w języku Ruby
Dr inż. Stanisław Polak
Grupa Systemów Komputerowych
https://www.icsr.agh.edu.pl/~polak/
Dr inż. Stanisław Polak 1
Mat
eriał
ydla
studen
tów
Infor
mat
yki wyd
ziału
IET
AGHw
Krako
wie
Plan wykładu
I Język RubyZmienneStruktury kontrolneTypy danychPodprogramyProgramowanie funkcyjneObiektowośćObsługa WWW
I Podstawowe pojęcia związane z tworzeniemaplikacji internetowych
I Podstawy języka dziedzinowego „Sinatra”I Framework Ruby on Rails
WstępPrzykład tworzenia aplikacjiKontrolerModelWidokLokalizacja i umiędzynarodowienieUwierzytelnianie i autoryzacja
Dr inż. Stanisław Polak 2
Notatki
Notatki
Organizacja przedmiotu
I Wykłady — co dwa tygodnie — przygotowaniedo danego ćwiczenia
I Ćwiczenia laboratoryjne — co dwa tygodnie,przez cały semestr
I Ocena końcowa obliczana na podstawie ilościpunktów za wykonanie:I Zestawu zadań programistycznych,
przeznaczonych do wykonania na zajęciachI Zestawu zadań domowych — termin oddania:
następne zajęcia
I Strona przedmiotu: https://www.icsr.agh.edu.pl/~polak/jezyki/ruby/
I Strona ćwiczeń laboratoryjnych:https://polak.icsr.agh.edu.pl/
Plan wykładówI Język RubyI Framework „Ruby on Rails”
Plan ćwiczeń
1. Składnia języka Ruby – typizacja
2. Przetwarzanie tekstu, wyrażenia regularne
3. Programowanie funkcyjne, obiektowość, TDD,programy ’gem’ oraz ’rake’
4. Interfejs Rack, podstawy języka dziedzinowego„Sinatra”
5. Framework „Ruby on Rails” — Kontroler oraztesty funkcjonalne
6. Framework „Ruby on Rails” — Model oraztesty jednostkowe
7. Framework „Ruby on Rails” — Widok oraztesty integracyjne
Dr inż. Stanisław Polak 3
Język Ruby Skrypty
Dr inż. Stanisław Polak 6
Notatki
Notatki
Język Ruby Skrypty
esectionWstęp
Uruchamianie kodu / skryptu Ruby
1 #!/ usr/bin/env ruby2 print "Hello World\n"
hello.rb
1 $ ruby -e ’print "hello world\n"’2 hello world3 $ ruby4 print "Hello World\n"5 Ctrl+D6 Hello World7 $ irb8 2.5.0 :001 > print "Hello World\n"9 Hello World
10 => nil11 2.5.0 :002 > exit12 $ ruby hello.rb13 Hello World14 $ chmod 755 hello.rb15 $ ./ hello.rb16 Hello World
Terminal Linux / macOS
Dr inż. Stanisław Polak 6
Język Ruby Skrypty
Konwencje nazewnicze dla funkcji / metod
I number.even?()
I string.upcase!()
I car.brand=(’Fiat’)
I array.size()
Dr inż. Stanisław Polak 8
Notatki
Notatki
Język Ruby Skrypty
Komentowanie kodu
Komentarze
1 # Ten cały wiersz jest komentarzem2 a = "#łańcuch znakowy" #Tu jest komentarz3 a = /#wyrażenie regularne/ #A tu kolejny komentarz4 #5 # Komentarz6 # Ciąg dalszy komentarza7 #
Osadzane bloki dokumentacji
1 =begin2 = NAZWA3 Przykładowy dokument RD45 = OPIS6 ...7 =end89 =begin html
10 <img src="Przyklad.png" alt="Rysunek 1." />11 <p>12 Oto kilka osadzonych HTML. W tym bloku mogę13 dołączać obrazy , użyć <span style="color: green">14 style </span > lub cokolwiek innego , co można zapisa
ć15 w HTML. Procesory RD, które nie wyprowadzają HTML ,16 będą to całkowicie ignorować.17 </p>18 =end19 if a > 220 print "a jest większe od 2\n"21 =begin2223 print "Ala ma kota\n"2425 =end26 b = 227 end28
Dr inż. Stanisław Polak 9
Język Ruby Skrypty
Wypisywanie danych
1 # ’to_s ’ is generally intended to return a human -readable representation of the object ,suitable for end users.
2 #’inspect ’, on the other hand , is intended fordebugging use , and should return arepresentation that is helpful to Rubydevelopers . The default ’inspect ’ method ,inherited from ’Object ’, simply calls ’to_s ’.
3 #Źródło: David Flanagan , Yukihiro Matsumoto , "TheRuby Programming Language"
4 ## #######################5 print(1.23, [4,5.67] , "8\ tdziewięć\n")6 puts7 printf("%e %s %s\n" ,1.23, [4 ,5.67], "8\ tdziewięć")8 puts9 puts(1.23, [4,5.67] , "8\ tdziewięć\n")
10 puts11 p(1.23 , [4,5.67], "8\ tdziewięć\n")12 puts13 p([{ pozycje: ["pomidor", "banan", "mango"],
sumarycznie: 200 }, { opcje_wysylki: ["dwa dni", "jeden dzień"]}, { metoda_platnosci: ["Gotówka", "Karta kredytowa"]}])
14 puts15 require "pp" #Ta linia jest wymagana dla wersji Ruby
< 2.5.016 pp(1.23, [4,5.67], "8\ tdziewięć\n")17 puts18 pp([{ pozycje: ["pomidor", "banan", "mango"],
sumarycznie: 200 }, { opcje_wysylki: ["dwa dni", "jeden dzień"]}, { metoda_platnosci: ["Gotówka", "Karta kredytowa"]}])
1 $ irb2 2.5.0 :001 > puts 1233 1234 => nil5 2.5.0 :002 > p 1236 1237 => 1238 2.5.0 :003 > pp 1239 123
10 => 12311 2.5.0 :004 > puts (123) ? true : false12 12313 => false14 2.5.0 :005 > p(123) ? true : false15 12316 => true17 2.5.0 :006 > pp(123) ? true : false18 12319 => true
Dr inż. Stanisław Polak 10
Notatki
Notatki
Język Ruby Skrypty
Wczytywanie danychWczytanie pojedynczej wartości
1 require ’scanf’2 puts "Podaj dwie liczby"3 a,b = scanf("%d%f")4 printf("a=%d b=%f\n",a,b)5 ## ############################6 puts "Podaj znak"7 znak = STDIN.getc # lub znak = $stdin.getc8 printf("znak=%c\n",znak)
Na wyjściu (konsola)
Podaj dwie liczby123 4.56a=123 b=4.560000
Podaj znakaznak=a
Dr inż. Stanisław Polak 11
Język Ruby Skrypty
Wczytywanie danychWczytanie pojedynczej linii tekstu
1 puts ’######################### ’2 puts "Wprowadź dane:"3 dane = gets()4 # lub5 # dane = readline()6 puts ’######################### ’7 puts "Wprowadzone dane:"8 print dane9 puts ’-------------------------’
10 p dane11 puts ’######################### ’
Na wyjściu#########################Wprowadź dane:Ala ma kota i psa#########################Wprowadzone dane:Ala ma kota i psa-------------------------"Ala\tma kota i\tpsa\n"#########################
Na wyjściu#########################Wprowadź dane:Ctrl+D#########################Wprowadzone dane:
-------------------------nil#########################
Dr inż. Stanisław Polak 12
Mat
eriał
ydla
studen
tów
Infor
mat
yki wyd
ziału
IET
AGHw
Krako
wieNotatki
Notatki
Język Ruby Skrypty
Wczytywanie danychWczytanie wielu linii tekstu
1 puts ’############# ’2 puts "Wprowadź dane:"3 while(dane = gets())4 puts ’############# ’5 puts "Wprowadzone dane:"6 puts dane7 puts ’-------------’8 p dane9 puts ’############# ’
10 puts "Wprowadź dane:"11 end
Na wyjściu#############Wprowadź dane:Ala#############Wprowadzone dane:Ala-------------"Ala\n"#############Wprowadź dane:ma kota i psa#############Wprowadzone dane:ma kota i psa-------------"ma kota i\tpsa\n"#############Wprowadź dane:Ctrl+D
1 puts ’############# ’2 puts "Wprowadź dane:"3 dane1 = STDIN.read()4 dane2 = readlines()5 puts ’############# ’6 puts "Wprowadzone dane:"7 puts dane18 puts dane29 puts ’-------------’
10 p dane111 p dane212 puts ’############# ’
Na wyjściu#############Wprowadź dane:Alama kota i psaCtrl+DAlama kota i psaCtrl+D#############Wprowadzone dane:Alama kota i psaAlama kota i psaCtrl+D-------------"Ala\nma kota i\tpsa\n"["Ala\n", "ma kota i \tpsa\n"]#############
Dr inż. Stanisław Polak 13
Język Ruby Skrypty
Umieszczanie danych w skrypcie
1 puts DATA.read2 END3 puts "Ten kod nie zostanie wykonany"4 Linia 25 Linia 3
Na wyjściu
puts "Ten kod nie zostanie wykonany"Linia 2Linia 3
Dr inż. Stanisław Polak 14
Notatki
Notatki
Język Ruby Skrypty
Umieszczanie danych w skrypciePrzykład zastosowania
1 #!/ usr/bin/env ruby2 require ’rdoc’3 if ARGV [0] == ’--man’4 manual = DATA.read5 # html = RDoc :: Markup :: ToHtml.new(RDoc :: Options.new)6 ansi = RDoc:: Markup :: ToAnsi.new7 puts ansi.convert(manual)8 end9 __END__
10 = Name1112 pmh -convert.rb - converts an OAI -PMH document into the DOAJ
format; optionally also into the DBLP or PBN.1314 = SYNOPSIS1516 pmh -convert.rb [--help] [--man] [--version] [--doajLogin
username] [--doajPass password] [startDate] [endDate]1718 == Examples1920 * +pmh -convert.rb+ Generate , in the current directory , DOAJ
file for the entire period of time , i.e., for all (input) records
2122 * <tt>pmh -convert.rb 2013 -01 -01 2013 -07-30</tt> Generate , in
the current directory , DOAJ file for a given period oftime.
2324 Author :: Stanisław Polak (mailto:[email protected])
pmh-convert.rb
Rysunek: Wyświetlanie podręcznika użytkownika zpoziomu konsoli systemowej
Dr inż. Stanisław Polak 15
Język Ruby Skrypty
Bloki BEGIN oraz END
1 puts "Kod skryptu"2 END {3 puts "Ten również"4 }5 END {6 puts "Ten kod jest wykonywany tuż po zakończeniu wykonywania
kodu skryptu"7 }8 BEGIN {9 puts "Ten kod jest wykonywany tuż przed rozpoczęciem
wykonywania kodu skryptu"10 }11 BEGIN {12 puts "Ten też"13 }
Na wyjściuTen kod jest wykonywany tuż przed rozpoczęciemwykonywania kodu skryptuTen teżKod skryptuTen kod jest wykonywany tuż po zakończeniu wykonywaniakodu skryptuTen również
1 # Obliczanie sumy liczb wczytanych z klawiatury , aż do naciśnięcia Ctrl+D2 # -n 7→ while($_ = gets) do3 # #treść skryptu4 # end5 # -p 7→ while($_ = gets) do6 # #treść skryptu7 # puts $_8 # end9 $ ruby -ne ’suma += $_.to_i; BEGIN { suma = 0 }; END { puts suma }’
10 1 #$_ = "1\n"11 2 #$_ = "2\n"12 10 #$_ = "10\n"13 Ctrl+D14 13
Przykład użycia w jednolinijkowcu
Dr inż. Stanisław Polak 16
Notatki
Notatki
Język Ruby Skrypty
Ładowanie skryptu
1 if FILE == $PROGRAM NAME2 #Zmienna ’__FILE__ ’ ma wartość "skrypt.rb"3 #Zmienna ’$PROGRAM_NAME ’ ma wartość "skrypt.rb"4 puts "Ten skrypt został uruchomiony z linii komend
"5 else6 #Zmienna ’__FILE__ ’ ma wartość "skrypt.rb"7 #Zmienna ’$PROGRAM_NAME ’ ma wartość "irb"8 puts "Ten skrypt został załadowany z poziomu
innego skryptu"9 end
skrypt.rb
1 $ irb2 2.5.0 :001 > load ’./ skrypt.rb’3 Ten skrypt został załadowany z poziomu innego
skryptu4 => true5 2.5.0 :002 > load ’./ skrypt.rb’6 Ten skrypt został załadowany z poziomu innego
skryptu7 => true8 2.5.0 :003 > require ’./ skrypt ’9 Ten skrypt został załadowany z poziomu innego
skryptu10 => true11 2.5.0 :004 > require ’./ skrypt ’12 => false13 # $ export RUBYLIB=$HOME/skrypty1:$HOME/skrypty214 $LOAD_PATH15 => ["/home/polak/skrypty1", "/home/polak/skrypty2",
"/home/polak/.rvm/rubies/ruby -2.5.0/ lib/ruby/site_ruby /2.5.0", ...]
1617 2.5.0 :005 > exit18 $ ruby skrypt.rb19 Ten skrypt został uruchomiony z linii komend
Konsola ’irb’
Dr inż. Stanisław Polak 17
Język Ruby Narzędzia
Ruby w systemie Linux / macOSMenedżery wersji Ruby
Ruby Version Manager (RVM)
1 $ sudo apt -get update2 $ sudo apt -get install libgdbm -dev libncurses5 -dev automake
libtool bison libffi -dev3 $ gpg --keyserver hkp:// keys.gnupg.net --recv -keys 409
B6B1796C275462A1703113804BB82D39DC0E34 $ curl -sSL https ://get.rvm.io | bash -s stable5 $ source ~/.rvm/scripts/rvm6 $ echo "source ~/.rvm/scripts/rvm" >> ~/. bashrc
Instalacja
Rbenv
1 cd2 git clone https :// github.com/rbenv/rbenv.git ~/. rbenv3 echo ’export PATH="$HOME /.rbenv/bin:$PATH"’ >> ~/. bashrc4 echo ’eval "$(rbenv init -)"’ >> ~/. bashrc5 exec $SHELL67 git clone https :// github.com/rbenv/ruby -build.git ~/. rbenv/
plugins/ruby -build8 echo ’export PATH="$HOME /.rbenv/plugins/ruby -build/bin:$PATH"’
>> ~/. bashrc9 exec $SHELL
Instalacja
Interpreter Ruby
1 $ rvm install <nazwaInterpretera >2 $ rbenv install <nazwaInterpretera >
Instalacja
1 $ rvm list known #wyświetlenie (nazw) dostępnych implementacjiwraz z numerami ich wersji
2 $ rvm upgrade <nazwaImplementacji > # np. rvm upgrade ruby34 $ rbenv install --list #wyświetlenie (nazw) dostępnych
implementacji wraz z numerami ich wersji5 $ rbenv install <nazwaInterpretera >
Aktualizacja
1 $ rvm use <nazwaInterpretera > --default #lub rvm use x.x.x --default
2 $ rbenv global <nazwaInterpretera >
Określanie domyślnego interpretera
Dr inż. Stanisław Polak 18
Notatki
Notatki
Język Ruby Narzędzia
Ruby w systemie Linux / macOSWażniejsze implementacje
Implementacje w języku C (CRuby)I MRI (ang. Matz’s Ruby Interpreter)
I Używany w Ruby ¬ 1.8I Tworzone jest drzewo składnioweI Korzysta z „zielonych wątków”
I YARV (Yet Another Ruby VM)I Używany w Ruby 1.9I Wirtualna maszyna RubyI Korzysta z wątków natywnych; używa GIL
(Global Interpreter Lock)I Oferuje kompilator JIT (Just-in-time) —
począwszy od wersji 2.6I Instalacja
1 $ rvm install ruby # instalacja najnowszej wersjiprodukcyjnej
2 $ rvm install ruby -head # instalacja najnowszejwersji deweloperskiej (testowej)
3 $ rvm install x.x.x # instalacja wersji o numerzex.x.x
InneI JRuby
I Implementacja w JavieI Używa wątków natywnych, brak GILI Używa kompilatora JITI Instalacja
1 $ rvm install jruby
I TruffleRubyI Korzysta z:
I Truffle — platforma do implementacjiwysokowydajnych środowisk językowychkorzystających z Javy oraz wirtualnej maszynyJavy
I GraalVM — wirtualna maszyna Javywyposażona w kompilator JIT o nazwie„Graal”
I Źródła: http://www.oracle.com/technetwork/oracle-labs/program-languages/downloads/
I Informacje o innych implementacjach —http://rvm.io/interpreters/
Dr inż. Stanisław Polak 19
Język Ruby Narzędzia
Ruby w systemie Linux / macOSPorównanie wydajności implementacji
1 def fibonacci(n)2 if n < 23 return n4 end5 return fibonacci(n - 2) + fibonacci(n - 1)6 end7 ## ###############8 def wątki9 i = 100 _000_000
10 2.times.map do11 Thread.new do12 50 _000_000.times { i -= 1 }13 end14 end.each (&: join) #Czekamy aż wszystkie wątki zakończą pracę15 # Znaczenie ’&: nazwa ’ - patrz slajd nr 6116 printf("Końcowa wartość i: %d\n", i)17 end
funkcje.rb
1 require ’benchmark ’2 load ’funkcje.rb’3 ## ###############4 czas_wykonania = Benchmark.realtime do |x|5 5.times { fibonacci (35) }6 end7 printf "Czas wykonania: %f\n", czas_wykonania8 ## ###############9 wątki()
skrypt.rb
1 $ rvm use ruby -2.6.12 $ time ruby skrypt.rb3 Czas wykonania: 10.2557804 Końcowa wartość i: 056 real 0m19 ,201s7 user 0m19 ,179s8 sys 0m0 ,013s9 $ time ruby --jit skrypt.rb # Włączona kompilacja JIT
10 Czas wykonania: 3.35290111 Końcowa wartość i: 01213 real 0m9 ,019s14 user 0m17 ,473s15 sys 0m0 ,684s16 # ###########################################17 $ rvm use 9.2.6.0 # Openjdk wersja "11.0.1"18 $ time ruby skrypt.rb19 Czas wykonania: 6.11213620 Końcowa wartość i: 464142852122 real 0m16 ,994s23 user 0m33 ,553s24 sys 0m0 ,313s25 $ time ruby -X-C skrypt.rb # Wyłączona kompilacja JIT26 Czas wykonania: 52.74284027 Końcowa wartość i: 99103692829 real 1m22 ,684s30 user 1m56 ,812s31 sys 0m0 ,340s32 # ###########################################33 $ rvm use truffleruby #GraalVM wersja "1.0.0 - rc13"34 $ time ruby skrypt.rb35 Czas wykonania: 2.04054336 Końcowa wartość i: 383583763738 real 0m4 ,596s39 user 0m7 ,361s40 sys 0m0 ,157s
Dr inż. Stanisław Polak 20
Notatki
Notatki
Język Ruby Narzędzia
RubyGems
I Standardowy menedżer pakietów (gemów) Rubiego — działa podobnie jak apt, yum, . . .I Dostępny wraz z Ruby 1.9
Przykłady użycia
1 gem install rails # zainstaluj gem ’Ruby on Rails ’2 gem fetch rails #pobierz gem ’Ruby on Rails ’, ale go nie instaluj3 gem uninstall rails #usuń gem ’Ruby on Rails ’4 gem list --local #wyświetl zainstalowane gemy5 gem list --remote #wyświetl dostępne gemy6 gem search NAPIS --remote # przeszukaj listę dostępnych gemów7 gem rdoc --all #stwórz dokumentacj ę RDoc/RI dla wszystkich zainstalowanych gemów8 gem cleanup #usuń stare wersje zainstalowanych gemów
Dr inż. Stanisław Polak 22
Język Ruby Narzędzia
Tworzenie i generowanie dokumentacjiProgram „rdoc”
1 # The program takes an initial word or phrase from2 # the command line (or in the absence of a3 # parameter from the first line of standard4 # input). In then reads successive words or5 # phrases from standard input and reports whether6 # they are angrams of the first word.7 #8 # Author :: Dave Thomas (mailto:[email protected])9 # Copyright :: Copyright (c) 2002 The Pragmatic Programmers ,
LLC10 # License :: Distributes under the same terms as Ruby1112 # This class holds the letters in the original13 # word or phrase. The is_anagram ? method allows us14 # to test if subsequent words or phrases are15 # anagrams of the original.16 class Anagram1718 # Remember the letters in the initial word19 def initialize(text)20 @initial_letters = letters_of(text)21 end22 # Test to see if a new word contains the same23 # letters as the original24 def is_anagram ?(text)25 @initial_letters == letters_of(text)26 end
27 # Determine the letters in a word or phrase28 #29 # * all letters are converted to lower case30 # * anything not a letter is stripped out31 # * the letters are converted into an array32 # * the array is sorted33 # * the letters are joined back into a string34 def letters_of(text)35 text.downcase.delete(’^a-z’).split(’’).sort.join36 end37 end3839 tester = Anagram.new(ARGV.shift || gets)40 ARGF.each do |text|41 puts "Anagram! " if tester.is_anagram? text42 end
anagram.rb
1 $ rdoc # Generuj pliki ’.html ’2 $ rdoc --format=ri # Generuj pliki ’.ri ’3 $ rdoc --format=pot # Generuj plik ’rdoc.pot ’
Generowanie dokumentacji
Dr inż. Stanisław Polak 23
Mat
eriał
ydla
studen
tów
Infor
mat
yki wyd
ziału
IET
AGHw
Krako
wieNotatki
Notatki
Język Ruby Narzędzia
Wyświetlanie manualaProgram „ri”
1 $ ri --help2 Usage: ri [options] [names ...]34 Where name can be:56 Class | Module | Module :: Class78 Class:: method | Class#method | Class.method | method9
10 gem_name: | gem_name:README | gem_name:History1112 All class names may be abbreviated to their minimum unambiguous form. If a name13 is ambiguous , all valid options will be listed.1415 A ’.’ matches either class or instance methods , while #method16 matches only instance and :: method matches only class methods.1718 README and other files may be displayed by prefixing them with the gem name19 they’re contained in. If the gem name is followed by a ’:’ all files in the20 gem will be shown. The file name extension may be omitted where it is21 unambiguous.2223 For example:2425 ri Fil26 ri File27 ri File.new28 ri zip29 ri rdoc:README3031 Note that shell quoting or escaping may be required for method names containing32 punctuation:3334 ri ’Array .[]’35 ri compact \!3637 To see the default directories ri will search , run:3839 ri --list -doc -dirs40 ...
Dr inż. Stanisław Polak 24
Język Ruby Narzędzia
Debugowanie skryptu
1 a=12 b=23 c=34 puts a5 puts b6 puts c
skrypt.rb
1 $ gem install byebug2 $ byebug skrypt.rb3 [1, 6] in /home/polak/skrypt.rb4 => 1: a=15 2: b=26 3: c=37 4: puts a8 5: puts b9 6: puts c
10 (byebug) display a11 1: a = nil12 (byebug) next1314 [1, 6] in /home/polak/skrypt.rb15 1: a=116 => 2: b=217 3: c=318 4: puts a19 5: puts b20 6: puts c21 1: a = 1
Debuger „Byebug”
1 $ ruby -rdebug skrypt.rb #Załadowanie biblioteki "debug"2 Debug.rb3 Emacs support available.45 skrypt.rb:1:a=16 (rdb:1) list7 [-4, 5] in skrypt.rb8 => 1 a=19 2 b=2
10 3 c=311 4 puts a12 5 puts b13 (rdb:1) display a14 1: a =15 (rdb:1) break 316 Set breakpoint 1 at skrypt.rb:317 (rdb:1) cont18 Breakpoint 1, toplevel at skrypt.rb:319 skrypt.rb:3:c=320 1: a = 121 (rdb:1) p b22 223 (rdb:1) p c24 nil25 (rdb:1) next26 skrypt.rb:4: puts a27 1: a = 128 (rdb:1) cont29 130 231 3
Dr inż. Stanisław Polak 25
Notatki
Notatki
Język Ruby Narzędzia
Alternatywna konsola RubyProgram „pry”
Wybrane cechyI Przeglądanie kodu źródłowegoI Podświetlanie składniI Przeglądanie dokumentacjiI System pomocy, na żywoI Integracja powłoki poleceń (uruchamianie
edytorów, uruchomianie ’git’ oraz ’rake’ zpoziomu ’pry’)
I Możliwość debugowania kodu
1 a=12 binding.pry #pierwsza pułapka3 b=24 c=35 binding.pry #druga pułapka6 puts a7 puts b8 puts c
skrypt.rb
1 $ gem install pry # Instalacja ’pry ’2 $ gem install pry -doc # Rozszerzona obsługa dokumentacji dla ’
pry ’3 $ pry4 [1] pry(main)> puts "Hello World"5 Hello World6 => nil7 [2] pry(main)> exit8 $ ruby -r pry skrypt.rb # Uruchomienie w trybie ,,debug ’’9 1: a=1
10 => 2: binding.pry #pierwsza pułapka11 3: b=212 4: c=313 5: binding.pry #druga pułapka14 6: puts a15 7: puts b16 [1] pry(main)> a17 => 118 [2] pry(main)> b19 => nil20 [3] pry(main)> Ctrl+D21 From: /home/polak/skrypt.rb @ line 5 :2223 1: a=124 2: binding.pry #pierwsza pułapka25 3: b=226 4: c=327 => 5: binding.pry #druga pułapka28 6: puts a29 7: puts b30 8: puts c31 9:3233 [1] pry(main)>
Dr inż. Stanisław Polak 26
Język Ruby Zmienne
Definiowanie zmiennych
1 #stałe2 STALA=13 =>14 STALA=25 (irb):2: warning: already initialized constant STALA6 => 27 # definiowanie zmiennych8 a = 109 b = 20
10 c = 3011 d = 4012 a, b, c, d = 10, 20, 30, 4013 # identyfikacja typu14 d.kind of? Integer15 => true16 d.class17 => Integer18 #zmiana typu19 x = 1020 => 1021 x.class22 => Integer23 x = "hello"24 => "hello"25 x.class26 => String
1 y = 202 => 203 y.to f4 => 20.05 54321.to s #kod dziesiątkowy6 => "54321"7 54321.to s(2) #kod dwójkowy8 => "1101010000110001"9 54321.to s(16) #kod szesnastkowy
10 => "d431"11 54321.to s(8) #kod ósemkowy12 => "152061"
Konwersja wartości
Dr inż. Stanisław Polak 27
Notatki
Notatki
Język Ruby Zmienne
Zasięg zmiennych
1 x = 102 => 103 defined? x4 => "local -variable"5 $x = 106 => 107 defined? $x8 => "global -variable"9 loopcounter = 10
10 LoopCounter = 2011 $welcome = "Welcome to Ruby"12 gets13 hello14 => "hello\n"15 $16 => "hello\n"17 require ’English ’18 => true19 $LAST READ LINE20 => "hello\n"21 $$22 => 1740323 @@total = 024 @total = 1025 Stala=1
Dr inż. Stanisław Polak 28
Język Ruby Struktury kontrolne
Instrukcja warunkowa if
Wyrażenie „if”
1 if warunek [then]2 kod ...3 [elsif warunek [then]4 kod ...]...5 [else6 kod ...]7 end
Składnia
1 if 10 < 20 then2 print "10 jest mniejsze niż 20"3 end
Przykład użycia
Modyfikator „if”
1 kod if warunek
Składnia
1 print "10 jest mniejsze niż 20" if 10 < 20
Przykład użycia
1 liczba = 52 znak = if liczba > 03 ’dodatni ’4 elsif liczba < 05 ’ujemny ’6 else7 ’zero’8 end9 znak
10 => "dodatni"
Dr inż. Stanisław Polak 29
Notatki
Notatki
Język Ruby Struktury kontrolne
Instrukcja warunkowa unless
Wyrażenie „unless”
1 unless warunek [then]2 kod3 [else4 kod ]5 end
Składnia
1 unless str.nil?2 puts str.length3 end4 # W Ruby >= 2.3 powyższe linie można zapisać nastę
pująco:5 # puts str &. length
Przykład użycia
Modyfikator „unless”
1 kod unless warunek
Składnia
1 puts str.length unless str.nil?
Przykład użycia
Dr inż. Stanisław Polak 30
Język Ruby Struktury kontrolne
Instrukcja wyboru
1 ## ####### Forma 1 #########2 case wyrażenie3 [when wyrażenie [, wyrażenie ...] [then]4 kod ]...5 [else6 kod ]7 end89 ## ####### Forma 2 #########
10 case11 [when wyrażenie_logiczne [, wyrażenie_logiczne ...] [then]12 kod ]...13 [else14 kod ]15 end
Składnia
1 liczba = 72 case liczba3 when 1,2,3 # Wykonuje: 1 === liczba || 2 === liczba || 3 ===
liczba4 "mały"5 when 4,5,66 "średni"7 when 7,8,98 "duży"9 else
10 "olbrzymi"11 end12 => "duży"13 ## #########################14 a = 215 case16 when a == 1, a == 217 "a ma wartość jeden lub dwa"18 when a == 319 "a ma wartość trzy"20 else21 "Nie potrafię określić wartości zmiennej a"22 end23 => "a ma wartość jeden lub dwa"24 ## #########################25 case url26 when /http:/27 "protokół HTTP"28 ...29 else30 "nieznany protokół"31 end
Przykład użycia
Dr inż. Stanisław Polak 31
Notatki
Notatki
Język Ruby Struktury kontrolne
Pętle while oraz until1 while warunek [do]2 kod3 end45 begin6 kod7 end while warunek89 kod while warunek
Składnia pętli „while”
1 line=nil2 while line !~ /^$/ do line = gets.chomp end3 ## ######################4 i=15 while i < 36 puts i7 i += 1 #W Ruby nie ma instrukcji : ’++ zmienna ’ / ’zmienna --’, itp.8 j = 29 end
10 puts j #Wypisze: 211 ## ######################12 i=113 begin14 puts i15 i += 116 j = 217 end while i < 3 #Ta konstrukcja nie jest zalecana przez Matz -a18 puts j #Wypisze: 219 ## ######################20 line = gets.chomp while line !~ /^$/
1 until warunek [do]2 kod3 end45 until while warunek67 begin8 kod9 end until warunek
Składnia pętli „until
1 line=nil2 until line =~ /^$/ do line = gets.chomp end3 ## ######################4 i=15 until i >= 3 do6 puts i7 i += 18 j = 29 end
10 puts j #Wypisze: 211 ## ######################12 i=113 begin14 puts i15 i += 116 j = 217 end until i >= 3 #Ta konstrukcja nie jest zalecana przez Matz -a18 puts j #Wypisze: 219 ## ######################20 line = gets.chomp until line =~ /^$/
Dr inż. Stanisław Polak 32
Język Ruby Struktury kontrolne
Instrukcje break, redo oraz next
1 i = 02 while p "Wyrażenie ’while’"3 i += 14 printf "\ti=%d\n", i5 case i6 when 27 puts "\tWykonuję ’next’"8 next9 when 4
10 puts "\tWykonuję ’redo’"11 redo12 when 613 puts "\tWykonuję ’break’"14 break15 end16 puts "\tJestem na końcu ’while’"17 end18 puts ’Koniec ’
Na wyjściu
Wyrażenie ’while’i=1Jestem na końcu ’while’Wyrażenie ’while’i=2Wykonuję ’next’Wyrażenie ’while’i=3Jestem na końcu ’while’Wyrażenie ’while’i=4Wykonuję ’redo’i=5Jestem na końcu ’while’Wyrażenie ’while’i=6Wykonuję ’break’Koniec
Dr inż. Stanisław Polak 33
Mat
eriał
ydla
studen
tów
Infor
mat
yki wyd
ziału
IET
AGHw
Krako
wieNotatki
Notatki
Język Ruby Struktury kontrolne
Pętla loop
1 #Petla nieskończona2 loop do3 puts "Witaj"4 end56 #Petla skończona7 i = 18 loop do9 puts i
10 i += 111 j = 212 break if i > 313 end14 puts j # undefined local variable or method ‘j’
Dr inż. Stanisław Polak 34
Język Ruby Struktury kontrolne
Pętla for oraz metody iteracyjne
1 for i in 1..8 do2 puts i3 end4 # Powyższy kod jest równoważny:5 # (1..8).each{ |i| puts i }6 ## ############7 strs = ["abc\n", "cdae\n", "zzas\n", "aaaa\n"]8 strs.each{ |s| s.chop! }9 p strs
10 ## ############11 5.times { |i| puts i }12 ## ############13 2.upto(4) { |i| puts i }14 ## ############15 4.downto(2) { |i| puts i }16 ## ############17 0.step(10, 2) { |i| puts i }18 ## ############19 0.step(10, 2) do |i|20 puts i21 redo22 end
Na wyjściu
Dr inż. Stanisław Polak 35
Notatki
Notatki
Język Ruby Typy danych Typy podstawowe
Typy liczboweI Integer
1 2 - 3 * 22 =>-43 1.hour + 90. minutes + 1. minute #Dostępne w RoR lub po
wykonaniu "require ’active_support /all ’"4 => 1 hour and 91 minutes5 1111111111111111111111*4006 => 444444444444444444444400
I FloatI Rational
1 Rational (1,3) + Rational (1,2) # 13 + 1
2 = 56
2 => (5/6)3 0.1r #Składnia dostępna począwszy od wersji 2.14 => (1/10)5 0.1r * 36 => (3/10)
I Complex
1 Complex (1,2)+Complex (2,3) # <=> (1+2i)+(2+3i)=(3+5i)2 => (3+5i)3 42ri #Składnia dostępna począwszy od wersji 2.14 => (0+(42/1)*i)
I Konwersje
1 Integer (10.898)2 => 103 Integer (0 b01110101) # konwersja z kodu binarnego4 => 1175 Integer (01231) # konwersja z kodu ó semkowego6 => 6657 Integer (0 xaabb) # konwersja z kodu szesnastkowego8 => 437079 Float (10)
10 =>10.011 Integer("aaa")12 ArgumentError: invalid value for Integer (): "aaa"13 Float("aaa")14 ArgumentError: invalid value for Float (): "aaa"
Dr inż. Stanisław Polak 38
Język Ruby Typy danych Typy podstawowe
Wyrażenia regularne
1 name = "Matz"2 name =~ /([[: lower :]]{2})/3 $‘4 => "M"5 $16 => "at"7 $’8 => "z"9 #Inne sposoby konstrukcji wyrażenia regularnego
10 name =~ %r|([[: lower :]]{2})|11 => 112 re = Regexp.new("([[: lower :]]{2})")13 md = re.match(name)14 => #<MatchData :0 xb7d41054 >15 md.pre match16 => "M"17 md.value at 118 => "at"19 md.post match20 => "z"
Dr inż. Stanisław Polak 39
Notatki
Notatki
Język Ruby Typy danych Typy podstawowe
Przedziały
1 1..10 # Zakres od 1 do 102 1...10 # Zakres od 1 do 934 (1..10).to_a # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]5 (1...10).to_a # => [1, 2, 3, 4, 5, 6, 7, 8, 9]67 (’a’..’l’).to_a # => ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"]8 (’Z’..’a’).to_a # => ["Z", "[", "\\" , "]", "^", "_", "‘", "a"]9
10 (’cab’..’car’).to_a # => [" cab", "cac", "cad", "cae", "caf", "cag", "cah", "cai", "caj", "cak", "cal", "cam", "can", "cao", "cap", "caq", "car "]
Dr inż. Stanisław Polak 40
Język Ruby Typy danych Typy podstawowe
PrzedziałyMetody
1 words = ’cab’..’car’2 words.min3 => "cab"4 words.max5 => "car"6 words.include?(’can’)7 => true8 words.reject {| subrange| subrange < ’cal’}9 => ["cal", "cam", "can", "cao", "cap", "caq", "car"]
10 words.each {|word| puts "Hello " + word}11 Hello cab12 Hello cac13 ...14 Hello car
Dr inż. Stanisław Polak 41
Notatki
Notatki
Język Ruby Typy danych Typy podstawowe
PrzedziałyPrzykłady zastosowania
1 while input = gets2 puts input + " triggered" if input =~ /start /..
input =~ /end/3 end
Na wyjściu
12startstarttriggered11triggered22triggeredendendtriggered12
1 score = 702 result =3 case score4 when 0..40: "Nie zaliczył (oblał test)"5 when 41..60: "Zaliczył"6 when 61..70: "Zaliczył z wysokim wynikiem"7 when 71..100: "Zaliczył z wyróżnieniem"8 else "Nieprawidłowy wynik testu"9 end
10 puts result
Dr inż. Stanisław Polak 42
Język Ruby Typy danych Typy podstawowe
Tablice zwykłe
1 days_of_week = Array.new(7)2 => [nil , nil , nil , nil , nil , nil , nil]3 days_of_week = Array.new(7, "today")4 => ["today", "today", "today", "today", "today", "today", "today"]5 days_of_week = Array[ "Mon", "Tues", "Wed", "Thu", "Fri", "Sat", "Sun" ]6 #lub7 days_of_week = [ "Mon", "Tues", "Wed", "Thu", "Fri", "Sat", "Sun" ]8 => ["Mon", "Tues", "Wed", "Thu", "Fri", "Sat", "Sun"]9 days_of_week.empty?
10 => false11 days_of_week.size12 => 713 days_of_week.length14 => 715 days_of_week[0]16 => "Mon"17 days_of_week.at(0)18 => "Mon"19 days_of_week.first20 => "Mon"21 days_of_week [0].class22 => String23 days_of_week.index("Wed")24 => 225 days_of_week[1, 3]26 => ["Tues", "Wed", "Thu"]27 days_of_week[1..3]28 => ["Tues", "Wed", "Thu"]
Dr inż. Stanisław Polak 43
Notatki
Notatki
Język Ruby Typy danych Typy podstawowe
Tablice zwykłe c.d.
1 matrix = [[1,2,3],[3,4,5],[5,6,7]]2 matrix [1]3 => [3, 4, 5]4 matrix[1][1]5 => 46 matrix [1,1]7 => [[3, 4, 5]]8 ## ##########################################9 operating_systems = ["Fedora", "SuSE", "RHEL", "Windows", "
macOS"]10 linux_systems = ["RHEL", "SuSE", "PCLinuxOS", "Ubuntu", "
Fedora"]11 operating_systems | linux_systems12 => ["Fedora", "SuSE", "RHEL", "Windows", "macOS", "PCLinuxOS",
"Ubuntu"]13 operating_systems & linux_systems14 => ["Fedora", "SuSE", "RHEL"]15 operating_systems - linux_systems16 => ["Windows", "macOS"]
17 days1 = ["Mon", "Tue", "Wed"]18 days2 = ["Thu", "Fri", "Sat", "Sun"]19 days = days1 + days220 days21 => ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]22 days123 => ["Mon", "Tue", "Wed"]24 ## ##########################################25 days1 = ["Mon", "Tue", "Wed"]26 days2 = ["Thu", "Fri", "Sat", "Sun"]27 days = days1.concat(days2)28 => ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]29 days30 => ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]31 days132 => ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]3334 ## ##########################################35 days1 = ["Mon", "Tue", "Wed"]36 days2 = ["Thu", "Fri", "Sat", "Sun"]37 days = days1 << days238 days39 => ["Mon", "Tue", "Wed", ["Thu", "Fri", "Sat", "Sun"]]40 days141 => ["Mon", "Tue", "Wed", ["Thu", "Fri", "Sat", "Sun"]]
Dr inż. Stanisław Polak 44
Język Ruby Typy danych Typy podstawowe
Tablice asocjacyjne
1 hash = { "jeden" => 1, "dwa" => 2, "trzy" => 3 }2 hash["jeden"]3 => 14 hash1 = {jeden:1, dwa:2, trzy :3} #Składnia dostępna począwszy od wersji 1.95 => {: jeden=>1, :dwa=>2, :trzy=>3}6 hash1[:jeden]7 => 18 histogram = Hash.new(0)9 => {}
10 histogram["Ala"]11 => 012 histogram["Ala"] += 113 => 114 histogram["Ala"]15 => 116 hash.has key?("jeden")17 => true18 hash.has value?("jeden")19 => false
Dr inż. Stanisław Polak 45
Mat
eriał
ydla
studen
tów
Infor
mat
yki wyd
ziału
IET
AGHw
Krako
wieNotatki
Notatki
Język Ruby Typy danych Typy podstawowe
Uporządkowane tablice asocjacyjne
1 h = {"c" => 3, "a" => 1, "b" => 2}2 h.each do |k, v|3 p [k, v]4 end56 #Wynik działania:7 # Ruby 1.9+ Ruby 1.88 ["c", 3] ["a", 1]9 ["a", 1] ["b", 2]
10 ["b", 2] ["c", 3]
1 h = {}2 h["a"] = "foo"3 h["b"] = "bar"4 p h5 # Na wyjściu:6 {"a"=>"foo", "b"=>"bar"}78 h["a"] = nil9 p h
10 #Na wyjściu:11 {"a"=>nil , "b"=>"bar"}1213 h.delete("a")14 h["a"] = "foo"15 p h16 #Na wyjściu:17 {"b"=>"bar", "a"=>"foo"}
Dr inż. Stanisław Polak 46
Język Ruby Typy danych Typy podstawowe
Łańcuchy znakówTworzenie i formatowanie
1 ## ##### tworzenie łańcucha #######2 myString = String.new3 => ""4 myString = String.new("This is my string. Get your own string")5 myString = String("This is also my string") #metoda ’String ’
jest metodą modułu "Kernel" - konwersja do typunapisowego
6 myString = "This is also my string"7 myString = ’This is also my string’8 ## ##### wypisanie łańcucha #######9 ’’#{myString} #{1+3}’’ lub %Q&#{ myString} #{1+3}& lub %&#{
myString} #{1+3}& lub %[#{ myString} #{1+3}]10 => "This is also my string 4"11 ’#{myString}’ lub %q&#{ myString}& lub %q(#{ myString})12 => "\#{ myString}"13 ‘ls‘ lub %x&ls& lub %x{ls}14 => Wynik wykonania komendy ’ls’15 ## ##### składnia HereDocs #######16 myText= <<DOC17 118 #{myString}19 DOC20 DOC21 => "1\nThis is also my string\n DOC\n"22 myText= <<-DOC23 124 #{myString}25 DOC26 => "1\nThis is also my string\n"
27 ## ##### Tworzenie tablicy napisów #######28 %w(1 2 aaa)29 => ["1", "2", "aaa"]30 ## ##### Formatowanie łańcucha #######31 a=132 b=233 "a=%d" % a34 => "a=1"35 "a=%d, b=%d" % [a,b]36 => "a=1, b=2"37 "c=%{c}, d=%{d}" % {:c=>3,:d=>4}38 => "c=3,d=4"39 ## ############# Wybrane metody ###############40 myString = "Hello"41 myString.length42 => 543 myString.size44 => 545 myString.empty?46 => false47 myString.sub(’H’,’h’)48 => "hello"49 myString50 => "Hello"51 myString.sub!(’H’,’h’)52 => "hello"53 myString54 => "hello"55 myString.object_id56 => 956512057 myString.sub!(’h’,’H’)58 => "Hello"59 myString.object_id60 => 9565120
Dr inż. Stanisław Polak 47
Notatki
Notatki
Język Ruby Typy danych Typy podstawowe
Łańcuchy znakówŁączenie, dostęp do fragmentów oraz porównywanie
1 ## ############# łączenie ###############2 myString = "Welcome " + "to " + "Ruby!" # konkatenacja (nie modyfikuje łańcucha z lewej)3 => "Welcome to Ruby!"4 myString = "Welcome " "to " "Ruby!" #jw.5 => "Welcome to Ruby!"6 myString = "Welcome ".concat("to ").concat("Ruby!") #dołącza do łańcucha z lewej ( modyfikuje go)7 => "Welcome to Ruby!"8 myString = "Welcome " << "to " << "Ruby!" #jw.9 => "Welcome to Ruby!"
10 ## ############# dostęp do fragmentów ###############11 myString["Ruby"]12 => "Ruby"13 myString["Perl"]14 => nil15 myString[3] #Ruby 1.9+16 => "c"17 myString[3].ord #Ruby 1.9+18 => 9919 myString[3].chr #Ruby 1.820 => "c"21 myString[11, 4]22 => "Ruby"23 myString[0..6]24 => "Welcome"25 myString[/[A-Z]/]26 => "W"27 myString.index(’’Ruby’’)28 => 11
Dr inż. Stanisław Polak 48
Język Ruby Typy danych Typy podstawowe
Łańcuchy znakówZastępowanie, substytucja, wstawianie
1 ## ##### podmiana #######2 myString = "Welcome to JavaScript!"3 myString["JavaScript"]= "Ruby"4 puts myString5 => "Welcome to Ruby!"6 myString = "Welcome to JavaScript!"7 myString[10] = "Ruby"8 puts myString9 => "Welcome toRubyJavaScript!"
10 myString = "Welcome to JavaScript!"11 myString[8..20] = "Ruby"12 puts myString13 => "Welcome Ruby!"14 ## ##### substytucja #######15 myString = "Welcome to PHP"16 myString.gsub("PHP", "Ruby")17 => "Welcome to Ruby"18 myString.replace("Goodbye to PHP!")19 => "Goodbye to PHP!"20 ## ##### powielanie #######21 myString * 322 => "Goodbye to PHP!Goodbye to PHP!Goodbye to PHP!"23 ## ##### wstawianie #######24 myString1 = "Paris in Spring"25 myString2 = "Paris in Spring"26 myString1 [8]=" the" # podmiana , a nie wstawienie przed27 => " the"28 myString129 => "Paris in theSpring"30 myString2.insert(8, " the")31 => "Paris in the Spring"32 myString233 => "Paris in the Spring"
Dr inż. Stanisław Polak 49
Notatki
Notatki
Język Ruby Typy danych Typy podstawowe
Łańcuchy znakówKonwersja
1 myArray = Array("ABCDEFGHIJKLMNOP")2 => ["ABCDEFGHIJKLMNOP"]3 myArray = "ABCDEFGHIJKLMNOP".split4 => ["ABCDEFGHIJKLMNOP"]5 myArray = "ABCDEFGHIJKLMNOP".split(//)6 => ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P"]7 "1000".to i8 => 10009 Integer("aaa")
10 # ArgumentError : invalid value for Integer (): "aaa"11 "aaa".to i #Nie wyrzuca wyjątku12 => 0
Dr inż. Stanisław Polak 50
Język Ruby Typy danych Typy podstawowe
Łańcuchy znakówNiemodyfikowalne napisy
1 # frozen string literal: true2 napis = "Stanisław"3 puts napis << " Polak" # RuntimeError : can ’t modify frozen String4 puts napis.dup << " Polak" #Wypisze: Stanisław Polak
Dr inż. Stanisław Polak 51
Notatki
Notatki
Język Ruby Typy danych Typy podstawowe
Symbole
1 # Tworzenie symboli2 s1 = :Polak3 s2 = :"Polak"4 %s(Stanisław Polak)5 => :"Stanisław Polak"6 # Tworzenie tablicy symboli7 %i(Stanisław Polak) #Dostępne w Ruby 2.0+8 => [: Stanisław, :Polak]9 ## ################
10 str1 = "Stanisław"11 str2 = "Stanisław"12 s1.object id == s2.object id13 => true14 str1.object id == str2.object id15 => false16 ## #############################17 "Stanisław" << " Polak"18 => "Stanisław Polak"19 :"Stanisław" << :" Polak"}20 NoMethodError: undefined method ‘<<’ for :Stanisław:Symbol21 ###############################22 :" Stanisław Polak".to s23 => "Stanisław Polak"24 "Stanisław Polak ".to sym25 => :" Stanisław Polak"26 ###############################27 :" Stanisław Polak".length # ⇔ :" Stanisław Polak".to_s.length28 =>1529 :Polak.gsub(’P’,’p’)30 NoMethodError: undefined method ‘gsub’ for :Polak:Symbol
1 key = "Jabłko"2 => "Jabłko"3 histogram[key] = 104 => 105 histogram[key]6 => 107 key.sub!("o", "a")8 => "Jabłka"9 key
10 => "Jabłka"11 histogram[key]12 => nil13 histogram["Jabłko"]14 => 1015 ## ########################16 key=:Jabłko17 => :Jabłko18 histogram[key] = 1019 => 1020 key.sub!("o", "a")21 NoMethodError: undefined method ‘sub!’ for :Jabłko:Symbol ...22 histogram[key]23 => 10
Dr inż. Stanisław Polak 52
Język Ruby Typy danych Typy podstawowe
Typ logiczny oraz pusty
1 a = ""2 a.nil?3 => false4 a = []5 a.nil?6 => false7 a = 08 a.nil?9 => false
10 a = nil11 a.nil?12 => true13 if 0 and [] and ’’’’14 "True"15 else16 "False"17 end18 => "True"19 if false or nil20 "True"21 else22 "False"23 end # => "False"
Dr inż. Stanisław Polak 53
Notatki
Notatki
Język Ruby Typy danych Typy podstawowe
Porównywanie wartości
1 #Przykład ze strony http :// stackoverflow .com/questions/7156955/ whats -the -difference -between -equal -eql -and
2 def eq(a, b)3 puts "#{[a, ’==’, b]} : #{a == b}"4 puts "#{[a, ’.eql?’, b]} : #{a.eql?(b)}"5 puts "#{[a, ’===’, b]} : #{a === b}"6 puts "#{[a, ’.equal?’, b]} : #{a.equal?(b)}"7 end89 eq(Object.new , Object.new)
10 eq(’all’, ’all’)11 eq(:all , :all)12 eq(3, 3)13 eq(1, 1.0)
Na wyjściu[#<Object:0x000000025e11c0>, "==",
#<Object:0x000000025e1198>] : false[#<Object:0x000000025e11c0>, ".eql?",
#<Object:0x000000025e1198>] : false[#<Object:0x000000025e11c0>, "===",
#<Object:0x000000025e1198>] : false[#<Object:0x000000025e11c0>, ".equal?",
#<Object:0x000000025e1198>] : false["all", "==", "all"] : true["all", ".eql?", "all"] : true["all", "===", "all"] : true["all", ".equal?", "all"] : false[:all, "==", :all] : true[:all, ".eql?", :all] : true[:all, "===", :all] : true[:all, ".equal?", :all] : true[3, "==", 3] : true[3, ".eql?", 3] : true[3, "===", 3] : true[3, ".equal?", 3] : true[1, "==", 1.0] : true[1, ".eql?", 1.0] : false[1, "===", 1.0] : true[1, ".equal?", 1.0] : false
Dr inż. Stanisław Polak 54
Język Ruby Podprogramy Funkcje
Funkcje
1 ## ##################2 # Definiowanie funkcji3 ## ##################4 def nazwa funkcji(par1, par2=wartość domyślna, ...)5 ...6 return wartość7 end8 ## #############################9 def good_bye(*guys)
10 "Do widzenia " + guys.join(" i ")11 end1213 ## #################14 #Wywoływanie funkcji15 ## #################1617 nazwa funkcji(arg1,arg2,...)18 ## #############################19 good_bye("Stanisławie","Marcinie")20 => "Do widzenia Stanisławie i Marcinie"
1 def funkcja(a=1,b:2,c:3)2 puts a3 puts b4 puts c5 end67 funkcja (1) #Wypisze: 1 2 3 w osobnych liniach8 funkcja (1,1) #... wrong number of arguments (2 for
0..1) ( ArgumentError )9 funkcja(c:20,b:10) #Wypisze: 1 10 20 w osobnych
liniach10 argumenty = { c:200,b:100 }11 funkcja(3,**argumenty) #Wypisze: 3 100 200 w
osobnych liniach12 def moja_funkcja((a,b))13 p a: a, b: b14 end15 moja_funkcja ([1 ,2]) #Wypisze: {:a=>1, :b=>2}
Dr inż. Stanisław Polak 55
Mat
eriał
ydla
studen
tów
Infor
mat
yki wyd
ziału
IET
AGHw
Krako
wieNotatki
Notatki
Język Ruby Podprogramy Bloki
Przykłady
1 # definiowanie bloków2 {|x,y,z| x + y + z }3 do |x,y,z|4 x + y + z5 end6 # przekazywanie bloku jako parametru wywołania metody7 a = [1,2,3].reject{|e| e.odd?}8 #przekształcenie w obiekt9 odd = lambda {|e| e.odd?}
10 odd = ->(e){e.odd?} #Składnia dostępna począwszy od wersji 1.9. "()" można pominąć11 even_numbers = [1,2,3]. reject &odd12 odd_number = [1,2,3]. select &odd13 odd.call(3)14 => true15 odd[3] # metoda ’[]’ - alias metody ’call ()’16 => true17 odd.(3) #Składnia dostępna począwszy od wersji 1.918 => true
Dr inż. Stanisław Polak 57
Język Ruby Podprogramy Bloki
Przykłady
1 def dwarazy2 yield3 yield4 end5 dwarazy { puts "Witaj" } #można również wywołać tak: dwarazy () { puts "Witaj" }6 #Na wyjściu:7 Witaj8 Witaj9
10 def dwarazy11 yield 112 yield 213 end14 dwarazy {|i| puts "#{i}. raz: Witaj"}15 #Na wyjściu:16 1. raz: Witaj17 2. raz: Witaj1819 def dwarazy(&blok)20 blok.call 1 # zmienna ’blo21 blok.call 222 end23 dwarazy {|i| puts "#{i}. raz: Witaj"}24 #Na wyjściu25 1. raz: Witaj26 2. raz: Witaj27 =begin28 Można również wywołać tak:29 dwarazy () {|i| puts "#{i}. raz: Witaj"}30 ale nie tak:31 dwarazy( {|i| puts "#{i}. raz: Witaj"} )32 =end
Dr inż. Stanisław Polak 58
Notatki
Notatki
Język Ruby Podprogramy Bloki
Argumenty bloków
1 i = "foo"2 j = "foo"3 puts "Przed blokiem: i = #{i}"4 puts "Przed blokiem: j = #{j}"5 3.times do |i|6 puts "i = #{i}"7 j = i8 k = 29 end
10 puts "Poza blokiem: i = #{i}"11 puts "Poza blokiem: j = #{j}"12 puts "Poza blokiem: k = #{k}"
Wynik dla Ruby 1.9
Przed blokiem: i = fooPrzed blokiem: j = fooi = 0i = 1i = 2Poza blokiem: i = fooPoza blokiem: j = 2’<main>’: undefined localvariable or method ‘k’ formain:Object (NameError)
Wynik dla Ruby 1.8
Przed blokiem: i = fooPrzed blokiem: j = fooi = 0i = 1i = 2Poza blokiem: i = 2Poza blokiem: j = 2undefined local variable ormethod ‘k’ for main:Object (NameError)
Dr inż. Stanisław Polak 59
Język Ruby Podprogramy Bloki
Zmienne lokalne dla bloków
1 j = 22 jj = 23 a = lambda {|;jj| j = 1; jj = 1} #Składnia dostępna począwszy od wersji 1.94 a.call()5 puts j # 16 puts jj # 2
Dr inż. Stanisław Polak 60
Notatki
Notatki
Język Ruby Podprogramy Bloki
Obiekt „Proc”
1 ## ####### Obiekt ’Proc ’ #############2 p = Proc.new { puts "Hello World" }3 p = proc {puts "Hello World"} #To samo co wyżej4 # proc <=> lambda , dla Ruby < 1.95 # proc <=> Proc.new , dla Ruby >= 1.96 p.call # wypisze ’Hello World ’7 p.class # zwróci ’Proc ’8 ## ############ Bloki #################9 { puts "Hello World"} #Błąd składniowy
10 a = { puts "Hello World"} #Błąd składniowy11 [1,2,3]. each {|x| puts x/2} #OK12 ## ################################13 def metoda(proc1 ,proc2)14 proc1.call15 proc2.call16 end17 a = Proc.new { puts "Pierwszy proc"}18 b = Proc.new { puts "Drugi proc"}19 metoda(a,b) #OK20 metoda{puts "Pierwszy proc" }{puts "Drugi proc"} #Błąd skł
adniowy
21 p = proc {|x| puts x}22 l = lambda {|x| puts x}23 puts p #<Proc :0 x00000001bca0d8@a .rb:1>24 puts l ##<Proc :0 x00000001bca0b0@a .rb:2 (lambda)>25 p.call #Zwraca nil26 l.call # ArgumentError : wrong number of arguments (0
for 1)27 p.call (1,2) #Wypisze: 1, pozostałe argumenty są
ignorowane28 l.call (1,2) # ArgumentError : wrong number of arguments
(2 for 1)29 ## ################################30 def metoda_lambda31 l = lambda { return } # ’return ’ - " wyskakujemy " z ’
lambda ’32 l.call33 puts "Hello world"34 end3536 def metoda_proc37 p = proc { return } #’return ’ - " wyskakujemy " z ’
metoda_proc ’38 p.call39 puts "Hello world"40 end4142 metoda_lambda #Wypisze: Hello World43 metoda_proc #Nic nie wypisze
Dr inż. Stanisław Polak 61
Język Ruby Podprogramy Bloki
Przekształcanie metody w obiekt ’Proc’
Wybieranie liczb nieparzystych
1 ## ##########2 # Dwuetapowo3 ## ##########4 odd = :odd?.to proc # Zmienna ’odd ’ zawiera obiekt klasy ’Proc ’, reprezentuj ący metodę o nazwie takiej
jak podany symbol5 p odd #Wypisze: <Proc :0x...(&: odd ?)6 p [1, 2, 3]. select (&odd) #Wypisze: [1, 3]7 ## ###########################################8 # zmienna = : nazwa_metody .to_proc}9 # obiekt.iterator (& zmienna)
10 # m11 # obiekt.iterator (&: nazwa_metody )12 ## ############13 # Jednoetapowo14 ## ############15 p [1, 2, 3]. select (&:odd?) #Wypisze: [1, 3]16 ## #############################################17 # obiekt.iterator (&: nazwa_metody ) ⇔ obiekt.iterator {| arg| arg. nazwa_metody }18 # operator ’&’ powoduje przekazanie nazwy metody do iteratora19 ## #############################################
Bez użycia bloku — z bezpośrednim użyciem obiektu ’Proc’
1 p [1, 2, 3]. select {|e| e.odd?} #Wypisze: [1, 3]
Z użyciem bloku
Dr inż. Stanisław Polak 62
Notatki
Notatki
Język Ruby Podprogramy Bloki
Domknięcia
1 =begin2 funkcja wykorzystuje trzy zmienne:3 ’y’ - dostępną dla użytkownika4 ’x’ - dostępną tylko wewnątrz funkcji ’mnozenie_przez ()’5 ’z’ - dostępną tylko wewnątrz funkcji ’mnozenie_przez ()’6 =end7 ## ##########################################################8 def mnozenie_przez(x)9 z=0
10 lambda {|y| z+= 1 ; printf "z=%d, %d*%d=",z,x,y; return x*y}11 end12 ## ##########################################################13 iloczyn_5_przez = mnozenie_przez (5) # Parametrowi ’x’ jest przypisywana wartość 514 iloczyn_6_przez = mnozenie_przez (6) # Parametrowi ’x’ jest przypisywana wartość 615 ## ##########################################################16 puts iloczyn_5_przez #Wypisze: #<Proc :0 x00000000c0de38@lambda .rb:8 (lambda)>17 x=1018 y=2019 z=3020 puts iloczyn_5_przez.call (10) # Wypisze: z=1, 5*10=5021 puts iloczyn_5_przez.call (11) # Wypisze: z=2, 5*11=5522 puts iloczyn_6_przez.call (12) # Wypisze: z=1, 6*12=7223 ## ##########################################################24 puts x #Wypisze: 1025 puts y #Wypisze: 2026 puts z #Wypisze: 20
1Fragment kodu, w którym zmienne lokalne zachowują swoją tożsamość
Dr inż. Stanisław Polak 63
Język Ruby Programowanie funkcyjne
Programowanie imperatywne a programowanie funkcyjne
Programowanie imperatywneI Skupia się na „jak”I Programy zawierają listę instrukcji, które
„mówią” komputerowi, co zrobić z danymiwejściowymi
Programowanie funkcyjneI Skupia się na „co”I Rozkłada problem w zestaw funkcji
Functional programming is like describing your problem to a mathematician. Imperative pro-gramming is like giving instructions to an idiot
(arcus, #scheme on Freenode)
1 n = 12 num_elements = 03 sum = 04 while num_elements < 105 if (n**2 % 5).zero?6 sum += n7 num_elements += 18 end9 n += 1
10 end11 sum12 => 275
Podejście imperatywne
1 (1.. Float :: INFINITY).lazy.select { |x| (x**2 % 5).zero? }.take (10).inject (:+)
2 => 275
Podejście funkcyjne
Dr inż. Stanisław Polak 64
Notatki
Notatki
Język Ruby Programowanie funkcyjne Zasady
Nie modyfikuj zmiennych
Nie
1 indeksy = [1, 2, 3]2 indeksy << 43 ## ######################4 hasz = {:a => 1, :b => 2}5 hasz[:c] = 36 ## ######################7 napis = "witaj"8 napis.gsub !(/t/, ’l’)
Tak
1 indeksy = [1, 2, 3]2 wszystkie_indeksy = indeksy + [4]3 ## ######################4 hasz = {:a => 1, :b => 2}5 nowy_hasz = hasz.merge (:c => 3)6 ## ######################7 napis = "witaj"8 nowy_napis = napis.gsub(/t/, ’l’)
Dr inż. Stanisław Polak 65
Język Ruby Programowanie funkcyjne Zasady
Bloki jako funkcje wyższego rzędu
1 open("/etc/passwd") {|plik| puts plik.size}
Funkcja, która zawiera „funkcję” na liście argumentów
1 def dodawacz(a)2 proc {|b| a + b}3 end4 dodawacz5 = dodawacz (5)5 puts dodawacz5.call (3) #Wypisze: 8
Funkcja, która zwraca „funkcję”
Dr inż. Stanisław Polak 66
Mat
eriał
ydla
studen
tów
Infor
mat
yki wyd
ziału
IET
AGHw
Krako
wieNotatki
Notatki
Język Ruby Programowanie funkcyjne Zasady
Częściowe zastosowanie funkcji oraz rozwijanie funkcji
1 suma = proc { |x, y, z| (x||0) + (y||0) + (z||0) }2 p suma.call(1, 2, 3) # 63 p suma[1, 2, 3] # 64 ## ############################5 # Częściowe zastosowanie funkcji (ang. partial function
application )6 suma_partial = proc { |x, y| proc { |z| x + y + z } }7 p suma_partial.call(1, 2).call (3) # 68 p suma_partial [1, 2][3] # 69 ## ############################
10 # Rozwijanie "funkcji" (ang. currying)11 suma_curry= proc { |x| proc { |y| proc { |z| x + y + z }
} }12 p suma_curry.call (1).call (2).call (3) # 613 p suma_curry [1][2][3] # 614 p suma.curry[1][2][3] # 615 ## ############################16 f = proc { |x, y, z| [x, y, z] }17 p f[4, 5, 6] # [4, 5, 6]18 p f[4][5 , 6] # nil19 p f[4, 5][6] # nil20 p f[4][5][6] # undefined method ‘[]’ for nil:NilClass (
NoMethodError )2122 g = f.curry23 p g[4, 5, 6] # [4, 5, 6]24 p g[4][5 , 6] # [4, 5, 6]25 p g[4, 5][6] # [4, 5, 6]26 p g[4][5][6] # [4, 5, 6]27 p g[4] # #<Proc :0 x00562b3a477028 >2829 gg = f.curry(2)
30 p gg[4, 5, 6] # [4, 5, 6]31 p gg[4][5 , 6] # [4, 5, 6]32 p gg[4, 5][6] # nil33 p gg [4][5][6] # nil34 p gg[4] # #<Proc :0 x00555ebc5edbc8 >3536 h = g[1] # ’x’ otrzymuje wartość 137 p h[4, 5, 6] # [1, 4, 5]38 p h[4, 5] # [1, 4, 5]39 p h[4][5] # [1, 4, 5]40 p h[4] # #<Proc :0 x000000019404c0 >4142 hh = gg[1] # ’x’ otrzymuje wartość 143 p hh[4, 5, 6] # [1, 4, 5]44 p hh[4, 5] # [1, 4, 5]45 p hh [4][5] # nil46 p hh[4] # [1, 4, nil]4748 i = h[2] # ’y’ otrzymuje wartość 249 p i[4, 5, 6] # [1, 2, 4]50 p i[4, 5] # [1, 2, 4]51 p i[4] # [1, 2, 4]52 p i # #<Proc :0 x00558a3d2a2b38 >5354 ii = hh[2] # ’y’ otrzymuje wartość 255 p ii[4, 5, 6] # wrong number of arguments (given 3,
expected 1..2) ( ArgumentError )56 p ii[4, 5] # nil57 p ii[4] # nil58 p ii # [1, 2, nil]5960 j = i[3] # ’z’ otrzymuje wartość 361 p j # [1, 2, 3]6263 jj = ii[3]64 p jj #nil
Dr inż. Stanisław Polak 67
Język Ruby Programowanie funkcyjne Zasady
Rozwijanie funkcjiPrzykład użycia
1 ## #################################2 # Normal definitions
3 # pattern:∑
f (n) for n ∈ [a . . . b]
4 ## #################################5 sum_ints = lambda do |a,b|6 s = 0 ; a.upto(b){|n| s += n } ; s7 end89 sum_of_squares = lambda do |a,b|
10 s = 0 ; a.upto(b){|n| s += n**2 } ;s11 end1213 sum_of_powers_of_2 = lambda do |a,b|14 s = 0 ; a.upto(b){|n| s += 2**n } ; s15 end1617 puts sum_ints .(1 ,5) #=> 1518 puts sum_of_squares .(1 ,5) #=> 5519 puts sum_of_powers_of_2 .(1 ,5) #=> 6220 ## ##########################################21 # Some refactoring to make some abstraction22 # Passing the sum mechanism itself23 ## ##########################################24 sum = lambda do |f,a,b|25 s = 0 ; a.upto(b){|n| s += f.(n) } ; s26 end
27 puts sum[lambda {|x| x},1,5] #=> 1528 puts sum[lambda {|x| x**2},1,5] #=> 5529 puts sum[lambda {|x| 2**x},1,5] #=> 6230 ## #################################31 # More refactoring using currying32 ## #################################3334 # generate the currying35 currying = sum.curry3637 # Generate the partial functions38 sum_ints = currying[lambda {|x| x}]39 sum_of_squares = currying[lambda {|x| x**2}]40 sum_of_powers_of_2 = currying[lambda {|x| 2**x}]4142 puts sum_ints [1,5] #=> 1543 puts sum_of_squares [1,5] #=> 5544 puts sum_of_powers_of_2 [1,5] #=> 62
Źródło: http://blog.khd.me/ruby/ruby-currying/
Dr inż. Stanisław Polak 68
Notatki
Notatki
Język Ruby Programowanie funkcyjne Zasady
Unikanie skutków ubocznych
Nie
1 [1,2,3]. each do |x|2 #kod z efektami ubocznymi3 end4 for i in [1,2,3] do5 #kod z efektami ubocznymi6 end
Dr inż. Stanisław Polak 69
Język Ruby Programowanie funkcyjne Funkcje wyższego rzędu
Metoda map()
Nie
1 wynik = []2 [1,2,3,4]. each do |x|3 wynik << x*24 end5 wynik #[2, 4, 6, 8]
Tak
1 wynik =[1,2,3,4].map do |x|2 x*23 end #[2, 4, 6, 8]
Dr inż. Stanisław Polak 70
Notatki
Notatki
Język Ruby Programowanie funkcyjne Funkcje wyższego rzędu
Metoda select()
Nie
1 wynik = []2 [1,2,3,4]. each do |x|3 wynik << x if x > 24 end5 wynik #[3 ,4]
Tak
1 wynik =[1,2,3,4]. select do |x|2 x > 23 end #[3, 4]
Dr inż. Stanisław Polak 71
Język Ruby Programowanie funkcyjne Funkcje wyższego rzędu
Metoda detect()
Nie
1 wynik = nil2 [1,2,3,4]. each do |x|3 if x > 24 wynik = x5 break6 end7 end8 wynik #3
Tak
1 wynik =[1,2,3,4]. detect do |x|2 x > 23 end #3
Dr inż. Stanisław Polak 72
Notatki
Notatki
Język Ruby Programowanie funkcyjne Funkcje wyższego rzędu
Metoda inject()
Nie
1 suma = 02 [1,2,3,4]. each do |x|3 suma += x4 end5 suma #10
Tak
1 suma = [1,2,3,4]. inject (0) do |aku , x|2 aku+x3 end #104 ## ###############################5 suma = [1,2,3,4]. inject(0, :+) #10
Dr inż. Stanisław Polak 73
Język Ruby Programowanie funkcyjne Funkcje wyższego rzędu
Metoda zip()
Nie
1 a = [1,2,3,4]2 b = [5,6,7,8]3 wynik =[]4 0.upto(a.length -1).each do |i|5 wynik << [a[i], b[i]]6 end7 wynik #[[1, 5], [2, 6], [3, 7], [4, 8]]
Tak
1 a = [1,2,3,4]2 b = [5,6,7,8]3 wynik = a.zip(b) #[[1, 5], [2, 6], [3, 7], [4, 8]]
Dr inż. Stanisław Polak 74
Notatki
Notatki
Język Ruby Programowanie funkcyjne Funkcje wyższego rzędu
Wybrane metody do tworzenia iteratorów
1 [1,2,3]. permutation (2).to_a2 => [[1, 2], [1, 3], [2, 1], [2, 3], [3, 1], [3, 2]]3 [1,2,3]. permutation.to_a4 => [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]5 ## ############################6 [1,2,3]. combination (2).to_a7 => [[1, 2], [1, 3], [2, 3]]8 ## ############################9 [0,1,2,3]. group_by {|x| x%2}
10 => {0=>[0, 2], 1=>[1, 3]}11 [0,0,0,1,1,2]. group_by {|x| x}.map {|k,v| v}12 => [[0, 0, 0], [1, 1], [2]]
Dr inż. Stanisław Polak 75
Język Ruby Programowanie funkcyjne Funkcje wyższego rzędu
Przykład użycia
1 (1.. Float :: INFINITY).lazy.select { |x| (x**2 % 5).zero? }.take (10).inject (:+)2 => 275
Dr inż. Stanisław Polak 76
Mat
eriał
ydla
studen
tów
Infor
mat
yki wyd
ziału
IET
AGHw
Krako
wieNotatki
Notatki
Język Ruby Obiektowość
Definiowanie klas i tworzenie obiektów
1 class Zwierze2 end34 puts Zwierze.class #Wypisze: Class5 zwierze = Zwierze.new6 p zwierze #Wypisze: #<Zwierze :0 x000000009c17d8 >
Dr inż. Stanisław Polak 78
Język Ruby Obiektowość Metody
Metody
1 class Zwierze2 @obiekt_self = self3 ## #################################4 ## #### Metoda instancyjna #########5 ## #################################6 def wypisz7 printf "%s %s\n", self, self.class8 end9 ## #################################
10 ## ####### Metoda klasowa ##########11 ## #################################12 def Zwierze.wypisz13 #def self.wypisz14 printf "%s %s %s %s\n", self , self.class , @obiekt_self , @obiekt_self.class15 end16 end17 ## #################################18 z=Zwierze.new19 z.wypisz #Wypisze: #<Zwierze :0 x00000002142d58 > Zwierze20 # To co powyżej jest równoważne z.send(’wypisz’)21 Zwierze.wypisz #Wypisze: Zwierze Class Zwierze Class22 # To co powyżej jest równoważne Zwierze.send(’wypisz’)
Dr inż. Stanisław Polak 79
Notatki
Notatki
Język Ruby Obiektowość Metody
Metoda initialize()
1 class Zwierze2 def initialize(nazwa)3 puts nazwa4 end5 end67 zwierze = Zwierze.new(’Pies’) #Wypisze: Pies
Dr inż. Stanisław Polak 80
Język Ruby Obiektowość Metody
Dostęp do metody klasowej z wnętrza metody instancyjnej
1 class Zwierze2 def metodaInstancyjna3 puts "Jestem metodą instancyjną"4 self.class.metodaKlasowa5 end67 def self.metodaKlasowa8 puts "Jestem metodą klasową"9 end
10 end11 ## ############################12 z = Zwierze.new13 z.metodaKlasowa #Błąd wykonania : undefined method ‘metodaKlasowa ’ ...14 ## ############################15 z.metodaInstancyjna # Wypisze:16 # Jestem metodą instancyjn ą17 # Jestem metodą klasową
Dr inż. Stanisław Polak 81
Notatki
Notatki
Język Ruby Obiektowość Metody
Dziedziczenie
1 class Zwierze #Klasą bazową jest Object2 def initialize3 puts ’Konstruktor Zwierze ’4 end5 end6 ## ###########################7 p Zwierze.superclass #Wypisze: Object8 p Zwierze.superclass.superclass #Wypisze:
BasicObject9 p Zwierze.superclass.superclass.superclass #Wypisze:
nil
10 class Pies < Zwierze11 def initialize12 super13 puts "Konstruktor Pies"14 end15 end16 ## ###########################17 Pies.new #Wypisze:18 # Konstruktor Zwierze19 # Konstruktor Pies
Hierarchia dziedziczenia w Ruby 1.9 Hierarchia dziedziczenia w Ruby ¬ 1.8
Zwierze
Object
BasicObject
Zwierze
Object
Dr inż. Stanisław Polak 82
Język Ruby Obiektowość Atrybuty
AtrybutyInstancyjne
1 class Zwierze2 @ilosc = 134 def wypisz_ilosc5 p @ilosc #Wbrew pozorom , wartością atrybutu ’
@ilosc ’ nie jest 16 end78 def self.wypisz_ilosc9 p @ilosc
10 end1112 # attr writer :gatunek13 def gatunek=(g)14 @gatunek = g15 end1617 # attr reader :gatunek18 def gatunek19 @gatunek20 end2122 attr accessor :wiek # attr_accessor ⇔ attr_reader
∪ attr_writer23 end
24 z = Zwierze.new25 z.wypisz_ilosc #Wypisze: nil26 Zwierze.wypisz_ilosc #Wypisze: 127 puts z.ilosc # ... undefined method ‘ilosc ’ for #<
Zwierze :0 x000000017923d0 > ( NoMethodError )28 puts z.@ilosc # ... syntax error , unexpected tIVAR ,
expecting ’(’29 puts @z.ilosc # ... undefined method ‘ilosc ’ for nil:
NilClass ( NoMethodError )30 z.gatunek = "Ssak"31 puts z.gatunek # Wypisze: "Ssak"32 z.wiek = 1033 puts z.wiek # Wypisze: 10
Dr inż. Stanisław Polak 83
Notatki
Notatki
Język Ruby Obiektowość Atrybuty
AtrybutyKlasowe
1 class Zwierze2 @@ilosc = 034 def initialize5 @@ilosc += 16 end78 def ilosc # metoda instancyjna9 @@ilosc
10 end1112 def self.ilosc # metoda klasowa13 @@ilosc14 end15 end16 ## #######################17 puts Zwierze.ilosc #Wypisze: 018 ## #######################19 class Pies < Zwierze20 @@ilosc = 1021 end22 ## #######################23 puts Pies.ilosc #Wypisze: 1024 puts Zwierze.ilosc #Wypisze: 1025 pies = Pies.new26 puts pies.ilosc #Wypisze: 1127 puts Pies.ilosc #Wypisze: 1128 puts Zwierze.ilosc #Wypisze: 11
Dr inż. Stanisław Polak 84
Język Ruby Obiektowość Atrybuty
Atrybuty klasowe, a atrybuty instancyjne klasy
Atrybut klasowy
1 class Zwierze2 # ’@@ilosc ’ jest atrybutem klasowym dzielonym przez klasę ’
Zwierze ’ i każdą z jej podklas3 # Kiedy tworzysz instancję klasy ’Zwierze ’ lub jej podklasy ,
tj. ’Pies ’,4 # to wartość zmiennej ’ilosc ’ zwiększa się5 @@ilosc = 067 def initialize8 self.class.ilosc += 1 #Wywołanie metod ’self.ilosc=’ oraz
’self.ilosc ’9 end
1011 def self.ilosc12 @@ilosc13 end14 def self.ilosc =( wartosc)15 @@ilosc = wartosc16 end17 end1819 class Pies < Zwierze20 end2122 8.times { Zwierze.new }23 4.times { Pies.new }2425 p Zwierze.ilosc #Wypisze: 1226 p Pies.ilosc #Wypisze: 12
Atrybut instancyjny klasy
1 class Zwierze2 # ’@ilosc ’ jest atrybutem instancyjnym (wyłącznie) klasy ’
Zwierze ’3 # Wartość zmiennej ’ilosc ’ ulega zwiększeniu , tylko wtedy
gdy tworzysz instancję klasy ’Zwierze ’ (nie podklasy ,tj. Pies)
4 @ilosc = 056 def initialize7 self.class.ilosc += 1 #Wywołanie metod ’self.ilosc=’ oraz
’self.ilosc ’8 end9
10 def self.ilosc11 @ilosc12 end13 def self.ilosc=( wartosc)14 @ilosc = wartosc15 end16 end1718 class Pies < Zwierze19 @ilosc = 020 end2122 8.times { Zwierze.new }23 4.times { Pies.new }2425 p Zwierze.ilosc #Wypisze: 826 p Pies.ilosc #Wypisze: 4
Dr inż. Stanisław Polak 85
Notatki
Notatki
Język Ruby Obiektowość Moduły
Moduły
1 module Math2 PI = 3.141592653589793 def Math.sqrt(x)4 # ..5 end6 ...7 end8 ## ########################9 Math.sqrt(2) # => 1.4142135623731
10 Math::sqrt(2) # => 1.414213562373111 Math::PI # => 3.1415926535897912 ## ########################13 module Brzeczyk14 def dzwon15 puts "BZZZZ!BZZZZ!BZZZZ!"16 end17 end18 ## ########################19 class Czasomierz20 def podaj_czas21 puts Time.now22 end23 end24 ## ########################25 class Budzik < Czasomierz26 include Brzeczyk27 end28 ## ########################29 b = Budzik.new30 b.podaj_czas # Sun Aug 05 17:24:08 +0200 200731 b.dzwon # BZZZZ!BZZZZ!BZZZZ!32 Budzik.dzwon # undefined method ‘dzwon ’ for Budzik:
Class ( NoMethodError )
1 class Budzik < Czasomierz2 extend Brzeczyk3 end4 ## ########################5 b = Budzik.new6 b.podaj_czas # Sun Aug 05 17:24:08 +0200 20077 b.dzwon # undefined method ‘dzwon ’ for #<Budzik :0
x0000000242c0c8 > ( NoMethodError )8 Budzik.dzwon #BZZZZ!BZZZZ!BZZZZ!9 zegarek = Czasomierz.new
10 zegarek.extend(Brzeczyk)11 zegarek.dzwon # BZZZZ!BZZZZ!BZZZZ!
Dr inż. Stanisław Polak 86
Język Ruby Obiektowość Moduły
Metody klas oraz modułówSterowanie kolejnością wykonywania
1 module Brzeczyk2 def podaj_czas3 puts "Brzeczyk: " + Time.now.to_s4 super5 end6 end7 ## ########################8 class Czasomierz9 def podaj_czas
10 puts "Czasomierz: " + Time.now.to_s11 end12 end13 ## ########################1415 class Budzik < Czasomierz16 include Brzeczyk17 def podaj_czas18 puts "Budzik: " + Time.now.to_s19 super20 end21 end2223 Budzik.new.podaj_czas
Na wyjściuBudzik: 2014-01-31 13:29:48 +0100Brzeczyk: 2014-01-31 13:29:48 +0100Czasomierz: 2014-01-31 13:29:48 +0100
1 module Brzeczyk2 def podaj_czas3 puts "Brzeczyk: " + Time.now.to_s4 super5 end6 end7 ## ########################8 class Czasomierz9 def podaj_czas
10 puts "Czasomierz: " + Time.now.to_s11 end12 end13 ## ########################1415 class Budzik < Czasomierz16 prepend Brzeczyk #Dostępne w Ruby >= 2.017 def podaj_czas18 puts "Budzik: " + Time.now.to_s19 super20 end21 end2223 Budzik.new.podaj_czas
Na wyjściuBrzeczyk: 2014-01-31 13:31:19 +0100Budzik: 2014-01-31 13:31:19 +0100Czasomierz: 2014-01-31 13:31:19 +0100
Dr inż. Stanisław Polak 87
Mat
eriał
ydla
studen
tów
Infor
mat
yki wyd
ziału
IET
AGHw
Krako
wieNotatki
Notatki
Język Ruby Obiektowość Moduły
Atrybuty instancyjne oraz klasowe modułów
1 module Brzeczyk2 @czas1 = 13 @@czas2 = 245 def self.czas16 @czas17 end89 def self.czas2
10 @@czas211 end12 end13 ## #################14 class Czasomierz15 include Brzeczyk1617 def self.czas118 @czas119 end2021 def self.czas222 @@czas223 end2425 def self.czas2=(czas)26 @@czas2=czas27 end28 end29 ## #################30 p Brzeczyk.czas1 # Wypisze: 131 p Czasomierz.czas1 # Wypisze: nil32 p Brzeczyk.czas2 # Wypisze: 233 p Czasomierz.czas2 # Wypisze: 234 Czasomierz.czas2 = 335 p Brzeczyk.czas2 # Wypisze: 336 p Czasomierz.czas2 # Wypisze: 3
1 module Brzeczyk2 @czas1 = 13 @@czas2 = 245 def self.czas1 # Tutaj ’self ’ oznacza moduł, więc
odbiorcą komunikatu "czas1" będzie tylkomoduł
6 @czas17 end89 def self.czas2
10 @@czas211 end12 end13 ## #################14 class Czasomierz15 include Brzeczyk16 extend Brzeczyk17 end18 ## #################19 p Czasomierz.czas1 # Wyjątek: undefined method ‘
czas1 ’ for Czasomierz :Class20 p Czasomierz.czas2 # Wyjątek: undefined method ‘
czas2 ’ for Czasomierz :Class
Dr inż. Stanisław Polak 88
Język Ruby Obiektowość Inne zagadnienia
Sprawdzanie typu obiektu
1 module Man2 end34 module Woman5 end67 class Person8 include Man9 end
1011 class Player < Person12 include Woman13 end1415 p = Player.new16 p.kind of? Player #true17 p.kind of? Person #true18 p.kind of? Man #true19 p.kind of? Woman #true20 #kind_of? <=> is_a?2122 p.instance of? Player #true23 p.instance of? Person #false24 p.instance of? Man #false25 p.instance of? Woman #false
Dr inż. Stanisław Polak 89
Notatki
Notatki
Język Ruby Obiektowość Inne zagadnienia
Obiekt „main”
1 def funkcja2 puts "Jestem metodą obiektu ’main’"3 end45 class Klasa6 def metoda7 puts "Jestem metodą obiektu ’Klasa’"8 funkcja ()9 end
10 end1112 puts self #Wypisze: main13 puts self.class #Wypisze: Object1415 o=Klasa.new16 o.metoda #Wypisze: Jestem metodą obiektu ’Klasa ’17 # Jestem metodą obiektu ’main ’
Dr inż. Stanisław Polak 90
Język Ruby Obiektowość Inne zagadnienia
Przeciążanie operatorów
1 class Liczba2 def initialize(a)3 @a = a4 end5 ## #############6 def +(b)7 @a + b8 end9 ## #############
10 def -@11 puts "zanegowałeś liczbę"12 end13 end14 liczba = Liczba.new(1)15 puts liczba +416 -liczba
Na wyjściu
5zanegowałeś liczbę
Dr inż. Stanisław Polak 91
Notatki
Notatki
Język Ruby Obiektowość Inne zagadnienia
Kontrola dostępu1 class Test2 public # każda metoda (poza initialize (), która jest prywatna) jest domyślnie publiczna3 def pub_met14 end56 private # metoda prywatna7 def priv_met18 end9
10 protected # wymienione niżej metody są chronione11 def prot_met112 end1314 def prot_met215 end16 end
1 class Test2 def pub_met13 end45 def priv_met16 end78 def prot_met19 end
1011 public :pub_met112 private :priv_met113 protected :prot_met114 end
Dr inż. Stanisław Polak 92
Język Ruby Obiektowość Inne zagadnienia
Kontrola dostępuPrzykład użycia
1 class Foo2 def a3 end45 # Wywołanie ’a()’ z jawnym ’self ’ jako odbiorcą6 def b7 self.a8 end9
10 # Wywołanie metody ’a()’ z niejawnym ’self ’ jako odbiorcą11 def c12 a13 end1415 publicprotectedprivate :a16 end17 ## #####################################18 class Foo1 < Foo19 end20 ## #####################################21 def safe_send(receiver , method , message)22 # Nie można używać ’send () ’, ponieważ omija zasady widoczności23 eval "receiver .#{ method}"24 rescue => e25 puts "#{ message }: #{e}"26 else27 puts "#{ message }: wywołanie metody powiodło się"28 end29 ## #####################################30 foo = Foo.new31 foo1 = Foo1.new32 safe_send(foo , :a, "jawny odbiorca ")33 safe_send(foo , :b, "jawny odbiorca ’self’ ")34 safe_send(foo , :c, "niejawny odbiorca ’self’")35 safe_send(foo1 , :a, "jawny odbiorca ")36 safe_send(foo1 , :b, "jawny odbiorca ’self’ ")37 safe_send(foo1 , :c, "niejawny odbiorca ’self’")
skrypt.rb
1 $ ruby skrypt.rb2 jawny odbiorca : wywołanie metody powiodło się3 jawny odbiorca ’self’ : wywołanie metody powiodło się4 niejawny odbiorca ’self’: wywołanie metody powiodło się5 jawny odbiorca : wywołanie metody powiodło się6 jawny odbiorca ’self’ : wywołanie metody powiodło się7 niejawny odbiorca ’self’: wywołanie metody powiodło się
1 $ ruby skrypt.rb2 jawny odbiorca : protected method ‘a’ called for #<Foo:0
x000000028a0960 >3 jawny odbiorca ’self’ : wywołanie metody powiodło się4 niejawny odbiorca ’self’: wywołanie metody powiodło się5 jawny odbiorca : protected method ‘a’ called for #<Foo1 :0
x000000028a0938 >6 jawny odbiorca ’self’ : wywołanie metody powiodło się7 niejawny odbiorca ’self’: wywołanie metody powiodło się
1 $ ruby skrypt.rb2 jawny odbiorca : private method ‘a’ called for #<Foo:0
x000000021b4840 >3 jawny odbiorca ’self’ : private method ‘a’ called for #<Foo :0
x000000021b4840 >4 niejawny odbiorca ’self’: wywołanie metody powiodło się5 jawny odbiorca : private method ‘a’ called for #<Foo1:0
x000000021b4818 >6 jawny odbiorca ’self’ : private method ‘a’ called for #<Foo1 :0
x000000021b4818 >7 niejawny odbiorca ’self’: wywołanie metody powiodło się
Dr inż. Stanisław Polak 93
Notatki
Notatki
Język Ruby Obsługa WWW
Model klient-serwerUsługa WWW
Serwer WWW
Adres IP
ProtokółPort
Przeglądarka WWW
Dr inż. Stanisław Polak 94
Język Ruby Obsługa WWW
Wybrane komendy (metody) protokołu HTTP
Komenda „GET”URL żądania:http://www.icsr.agh.edu.pl/index.html
1 GET /index.html HTTP /1.12 Host: www.icsr.agh.edu.pl3
Żądanie
1 HTTP /1.1 200 OK2 Date: Mon , 09 Aug 2013 17:02:08 GMT3 Server: Apache /2.4.4 (UNIX)4 Content -Length: 17765 Content -Type: text/html; charset=utf -867 <!DOCTYPE html>8 <html>9 ...
10 </html>
Odpowiedź
Komenda „POST”URL żądania: http://www.icsr.agh.edu.pl/cgi-bin/search.cgi
1 POST /cgi -bin/search.cgi HTTP /1.12 Host: www.icsr.agh.edu.pl3 Content -Length: 4645 query=alpha+complex&casesens=false&cmd=submit
Żądanie
1 HTTP /1.1 200 OK2 Date: Mon , 09 Aug 2013 17:02:20 GMT3 Server: Apache /2.4.4 (UNIX)4 Content -Length: 17765 Content -Type: text/html; charset=utf -86 Connection: close78 <!DOCTYPE html>9 <html>
10 ...11 </html>
Odpowiedź
Dr inż. Stanisław Polak 95
Notatki
Notatki
Język Ruby Obsługa WWW
Wysyłanie danych z formularza HTML
Zatwierdzanie danych 7−→ kodowanie 7−→ wysyłanie do serwera WWW
1 <form method ="..." enctype ="..." action="...">
2 ...3 </form>
I GETI POST
I application/x-www-form-urlencodedI multipart/form-data
Dr inż. Stanisław Polak 96
Język Ruby Obsługa WWW
Kodowanie „application/x-www-form-urlencoded”Przykład
1 <form action="http :// www.serwer.com/script">2 Login: <input name="login" type="TEXT"><br>3 Password: <input name="password" type="PASSWORD">4 </form>
Dokument HTML
Login: Jan
Password: Kowalski (Nowak)
1 login=Jan&password=Kowalski +%28 Nowak %29
Zakodowane dane
Dr inż. Stanisław Polak 97
Mat
eriał
ydla
studen
tów
Infor
mat
yki wyd
ziału
IET
AGHw
Krako
wieNotatki
Notatki
Język Ruby Obsługa WWW
Kodowanie „multipart/form-data”Przykład
1 <form action="..." method="POST" enctype="multipart/form -data">2 <input name="login" type="TEXT">3 <input name="password" type="PASSWORD">4 <input name="file" type="FILE" accept="image/jpeg ,image/gif">5 </form>
Jan
Kowalski (Nowak)
image.jpg
1 POST /skrypt HTTP /1.02 Content -Length: 7753 Content -Type: multipart/form -data; boundary =------------------------815276501818664599101790669245 --------------------------81527650181866459910179066926 Content -Disposition: form -data; name="login"78 Jan9 --------------------------8152765018186645991017906692
10 Content -Disposition: form -data; name="password"1112 Kowalski (Nowak)13 --------------------------815276501818664599101790669214 Content -Disposition: form -data; name="file"; filename="image.jpg"15 Content -Type: image/jpeg16 Content -Transfer -Encoding: binary1718 The content of ’image.jpg’19 --------------------------8152765018186645991017906692
Dr inż. Stanisław Polak 98
Język Ruby Obsługa WWW Interfejs Rack
Użycie „Rack”Przykład 1
1 #!/ usr/bin/env ruby2 require ’rack’34 class HelloWorld5 def call(env)6 sleep (10) #uśpij program na 10 sekund7 return [200, {}, ["Hello world!"]]8 end9 end
1011 Rack:: Handler :: WEBrick.run(12 HelloWorld.new ,13 :Port => 900014 )
helloworld.rb
1 $ chmod 755 ./ helloworld.rb2 $ ./ helloworld.rb3 [2014 -04 -14 10:43:16] INFO WEBrick 1.3.14 [2014 -04 -14 10:43:16] INFO ruby 2.1.1 (2014 -02 -24)
[x86_64 -linux]5 [2014 -04 -14 10:43:16] INFO WEBrick :: HTTPServer#
start: pid =9026 port =90006 localhost - - [14/ Apr /2014:10:44:04 CEST] "GET /
HTTP /1.1" 200 127 - -> /
1 $ curl localhost :90002 Hello world!
Dr inż. Stanisław Polak 100
Notatki
Notatki
Język Ruby Obsługa WWW Interfejs Rack
Użycie „Rack”Przykład 2
1 class HelloWorld2 def call(env)3 return [4 200,5 {’Content-Type’ => ’text/html’},6 ["Hello world!"]7 ]8 end9 end
1011 run HelloWorld.new
config.ru
1 $ rackup # ⇐⇒ rackup config.ru2 ...3 * Listening on tcp ://0.0.0.0:92924 $ rackup -p 13375 ...6 * Listening on tcp ://0.0.0.0:1337
1 $ curl localhost :92922 Hello world!
Dr inż. Stanisław Polak 101
Język Ruby Obsługa WWW Interfejs Rack
Parametr ’env’
1 class HelloWorld2 def call(env)3 odpowiedź=env.map do |klucz ,wartość|4 klucz.to_s+"="+wartość.to_s+"<br>"5 end6 return [7 200,8 {’Content -Type’ => ’text/html;charset=
utf -8’},9 odpowiedź
10 ]11 end12 end
helloworld.rb
Dr inż. Stanisław Polak 102
Notatki
Notatki
Język Ruby Obsługa WWW Interfejs Rack
Obsługa formularzy HTML
1 <form action="http :// localhost :9292/">2 <input type="TEXT" name="a" value="ą" />3 <input type="TEXT" name="b" value="(" />4 <input type="TEXT" name="a" value="1" />5 <input type="SUBMIT">6 </form>
1 class HelloWorld2 def call(env)3 odpowiedź = ""4 # Odczytywanie danych otrzymanych od przeglądarki5 odpowiedź << env[’QUERY STRING’] #Dane
otrzymane (metodą GET) od przeglądarki6 odpowiedź << env[’rack.input’].read #Dane
otrzymane (metodą POST) od przeglądarki78 #Wysyłanie odpowiedzi do przeglądarki9 return [
10 200,11 {’Content -Type’ => ’text/html’},12 [odpowiedź]13 ]14 end15 end
helloworld.rb
Dr inż. Stanisław Polak 103
Język Ruby Obsługa WWW Interfejs Rack
Obsługa formularzy HTMLObiekt Rack::Request
1 <form action="http :// localhost :9292/">2 <input type="TEXT" name="a[]" value="ą" />3 <input type="TEXT" name="b" value="(" />4 <input type="TEXT" name="a[]" value="1" />5 <input type="SUBMIT">6 </form>
1 class HelloWorld2 def call(env)3 req = Rack::Request.new(env)4 odpowiedź = [5 "a="+req.params[’a’][0]+"<br>",6 "a="+req.params[’a’][1]+"<br>",7 "b="+req.params[’b’] # zamiast "req.params[’b ’]"
można użyć "req[’b ’]"8 ]9 return [
10 200,11 {’Content -Type’ => ’text/html;charset=
utf -8’},12 odpowiedź13 ]14 end15 end
helloworld.rb
Dr inż. Stanisław Polak 104
Notatki
Notatki
Język Ruby Obsługa WWW Interfejs Rack
Obsługa formularzy HTMLObiekt Rack::Response
1 class HelloWorld2 def call(env)3 req = Rack:: Request.new(env)4 res = Rack::Response.new5 res.write("a="+req.params[’a’][0]+"<br >") #Dopisuje podany tekst do ciała odpowiedzi6 res.write("a="+req.params[’a’][1]+"<br >")7 res.write("b="+req.params[’b’])8 res[’Content -Type’] = ’text/html;charset=utf -8’ # Ustawienie nagłówka "Content -type"9 res.status = 200 #zbędne , gdyż jest to domyślny kod statusu
10 res.finish #zwróć odpowiedź w postaci ( trzyelementowej ) tablicy11 end12 end
helloworld.rb
Dr inż. Stanisław Polak 105
Język Ruby Obsługa WWW Interfejs Rack
Tworzenie aplikacji pośredniczącej („Middleware”)
1 # Źródło: http :// code.tutsplus.com/articles/exploring -rack --net -329762 class ToUpper3 # Our class will be initialize with another Rack app4 def initialize(app)5 @app = app6 end78 def call(env)9 # First , call ‘@app ‘
10 status , headers , body = @app.call(env)1112 # Iterate through the body , upcasing each chunk13 upcased_body = body.map { |chunk| chunk.upcase }1415 # Pass our new body on through16 [status , headers , upcased_body]17 end18 end19 ## ###############################################20 class Hello21 def self.call(env)22 [ 200, {"Content -Type" => "text/plain"}, ["Hello from Rack!"] ]23 end24 end25 ## ###############################################26 use ToUpper # Tell Rack to use our newly -minted middleware27 run Hello28 # Odpowiednik : app = ToUpper.new(Hello); run app
config.ru
Dr inż. Stanisław Polak 106
Notatki
Notatki
Język Ruby Obsługa WWW Interfejs Rack
Aplikacja pośredniczącaPrzekazywanie parametrów
1 class ToUpper2 def initialize(app, param, &blok)3 puts app4 puts app.class5 puts ’-’ * 106 puts param7 puts param.class8 puts ’-’ * 109 blok.call(’Napis’)
10 end1112 ...13 end1415 class Hello16 ...17 end1819 # use(middleware, *args, &block)20 use ToUpper, ’Argument’ { |arg| puts arg }21 run Hello
config.ru
Na wyjściu
HelloClass----------ArgumentString----------Napis
Dr inż. Stanisław Polak 107
Język Ruby Obsługa WWW Interfejs Rack
Ogólnodostępne aplikacje pośredniczącePrzykład użycia
1 require ’./ helloworld ’2 require ’rack/contrib ’34 use Rack::Static , :urls => ["/css", "/images"], :root => "
public"5 use Rack:: ContentType , "text/plain"6 use Rack:: BounceFavicon7 use Rack::Reloader , 08 run HelloWorld.new
config.ru
1 <link rel="stylesheet" href="/css/style.css">
Dokument HTML
1 h1 {color: red}
public/css/style.css
Dr inż. Stanisław Polak 108
Mat
eriał
ydla
studen
tów
Infor
mat
yki wyd
ziału
IET
AGHw
Krako
wieNotatki
Notatki
Podstawowe pojęcia związane z tworzeniem aplikacji internetowych
Framework
I Dostarcza szkieletu do tworzenia aplikacji lub jej wybranych częściI Dostarcza zbioru ogólnych funkcjonalnościI Gotowe komponenty do budowy aplikacji WWWI Ułatwia proces wdrożania nowego pracownikaI Nie jest gotową aplikacją — jest zbiorem kodu i pewnych metod postępowania, dzięki którym
można efektywnie budować aplikacjeI Typowe cechy:
I Odwrócenie sterowaniaI Domyślne zachowanieI RozszerzalnośćI Zamknięta struktura wewnętrzna
I Typowe elementy:I Mechanizm uruchamiania i przetwarzania akcjiI Mechanizm tworzenia logiki biznesowej aplikacjiI Zarządzanie konfiguracjąI Zarządzanie komunikacją z bazą danychI Obsługa formularzyI System szablonówI Obsługa błędówI Mechanizmy bezpieczeństwa, uwierzytelniania i kontroli dostępuI Generatory kodu
Dr inż. Stanisław Polak 109
Podstawowe pojęcia związane z tworzeniem aplikacji internetowych
Wzorzec projektowy MVCŚrodowisko WWW
I MVC (ang. Model-View-Controller) —Model-Widok-Kontroler
I Podstawowe komponenty aplikacji:I Model → logika biznesowaI Widok→ logika prezentacjiI Kontroler → logika sterowania
I Bazuje na klasycznym wzorcu MVCI Zalety:
I StandaryzacjaI NiezależnośćI Łatwość modyfikacjiI Szybkość
I Wada: ZłożonośćI Kiedy stosować?
I Złożone aplikacjeI Potrzeba utrzymywania i dostosowywania do
nowych potrzebI Wyznaczenie obszarów kompetencjiI Wielokrotna używalność
Kontroler Widok
Model
Serwer
Klient
żądanie HTTP odpowiedź HTTP
Dr inż. Stanisław Polak 110
Notatki
Notatki
Podstawowe pojęcia związane z tworzeniem aplikacji internetowych
Wzorzec „Active record”
1 product = Product.new2 product.name = "Komputer"3 product.price = 123.454 product.save()
Dodanie nowego wiersza w tabeli
1 INSERT INTO products (name , price) VALUES (’Komputer’, 123.45);
SQL-owy odpowiednik powyższego kodu
1 b = Product.find (1)
Wyszukiwanie w bazie danych
1 SELECT * FROM products WHERE (products.id = 1)LIMIT 1; -- MySQL lub PostgreSQL
SQL-owy odpowiednik powyższego kodu
Dr inż. Stanisław Polak 111
Podstawowe pojęcia związane z tworzeniem aplikacji internetowych
CRUD
Działanie Instrukcja SQLCreate INSERTRead SELECTUpdate UPDATEDelete DELETE
Dr inż. Stanisław Polak 112
Notatki
Notatki
Podstawowe pojęcia związane z tworzeniem aplikacji internetowych
System szablonów
1 require ’erb’23 class Strona4 attr_accessor :tytul5 attr_accessor :produkty67 def renderuj(sciezka)8 zawartosc = File.read(File.expand_path(sciezka)) # Wczytaj9 # treść
10 #szablonu
11 t = ERB.new(zawartosc)12 t.result(binding) # Dokonaj ewaluacji kodu szablonu13 # znajdującego się w zmiennej ’zawartosc
’,14 # a następnie zwróć wygenerowany
dokument15 # HTML16 # Funkcja ’binding ()’ tworzy obiekt klasy ’Binding ’17 # (domknięcie) - obiekty tej klasy enkapsuluj ą kontekst18 # wykonania (wartość zmiennych , ...) w określonym miejscu19 # kodu oraz zachowują ten kontekst do wykorzystania w20 # przyszłości21 end22 end2324 stronaWWW = Strona.new25 stronaWWW.tytul = ’Tytuł strony ’26 stronaWWW.produkty = %w[Produkt1 Produkt2]27 puts stronaWWW.renderuj(’szablon.html.erb’)
skrypt.rb
1 <html>2 <head>3 <title><%= @tytul %></title >4 </head>5 <body>6 <ul>7 <% for produkt in @produkty %>8 <li><%= produkt %></li>9 <% end %>
10 </ul>11 </body>12 </html>
szablon.html.erb
1 <html>2 <head>3 <title>Tytuł strony </title>4 </head>5 <body>6 <ul>7 <li>Produk1 </li>8 <li>Produkt2 </li>9 </ul>
10 </body>11 </html>
Wynikowy dokument HTML
Dr inż. Stanisław Polak 113
Podstawowe pojęcia związane z tworzeniem aplikacji internetowych
RESTI Representational State Transfer
Zasób GET PUT POST DELETEKolekcja URI ta-kich jak http://przyklad.pl/uzytkownik/
Listuj URI i byćmoże inne szcze-góły członków ko-lekcji.
Zastąp całą kolek-cję inną kolekcją.
Utwórz nowywpis w kolekcji.Nowy URL jestautomatycznieprzydzielany wpi-sowi i zwykle jestzwracany przezoperację.
Usuń całą kolekcję.
Elementy URItakie jak http://przyklad.pl/uzytkownik/13
Pobierz reprezen-tację podanegoczłonka kolek-cji, wyrażoną wokreślonym typiemediów interneto-wych.
Zastąp podanegoczłonka kolekcji lubjeśli nie istnieje,utwórz go.
Traktuj podanegoczłonka jako kolek-cję samą w sobie iutwórz w niej nowywpis.
Usuń podanegoczłonka kolekcji.
Dr inż. Stanisław Polak 114
Notatki
Notatki
Podstawy języka dziedzinowego „Sinatra”
Przykład „Hello World”
1 require ’sinatra ’2 require ’sinatra/reloader ’ if development? # Wymaga gema ’sinatra -contrib ’34 get ’/witaj ’ do5 "Witaj Świecie\n"6 end
skrypt.rb
1 $ ruby skrypt.rb2 [2017 -06 -30 18:17:33] INFO WEBrick 1.3.13 [2017 -06 -30 18:17:33] INFO ruby 2.4.1 (2017 -03 -22) [x86_64 -linux]4 == Sinatra (v2.0.0) has taken the stage on 4567 for development with backup from WEBrick5 [2017 -06 -30 18:17:33] INFO WEBrick :: HTTPServer#start: pid =3521 port =4567
Uruchamianie aplikacji
1 $ curl http :// localhost :4567/ witaj2 Witaj Świecie
Wykonywanie żądania
Dr inż. Stanisław Polak 116
Podstawy języka dziedzinowego „Sinatra”
TrasyDefiniowanie
1 get ’/’ do2 .. wyświetl coś ..3 end45 post ’/’ do6 .. utwórz coś ..7 end89 put ’/’ do
10 .. zastąp coś ..11 end1213 patch ’/’ do14 .. zmodyfikuj coś ..15 end1617 delete ’/’ do18 .. unicestw coś ..19 end20 ...
Dr inż. Stanisław Polak 117
Notatki
Notatki
Podstawy języka dziedzinowego „Sinatra”
TrasyDopasowywanie
1 get ’/witaj ’ do2 "Pierwsza trasa\nhasz ’params ’ zawiera: #{params.inspect }\n"3 end45 get ’/witaj ’ do #Ta trasa nie zostanie (nigdy) dopasowana6 "Druga trasa\nhasz ’params ’ zawiera: #{ params.inspect }\n"7 end89 get ’/witaj/:nazwa’ do
10 "Trzecia trasa\nhasz ’params ’ zawiera: #{params.inspect }\n"11 end
1 $ curl http :// localhost :4567/ witaj2 Pierwsza trasa3 hasz ’params ’ zawiera: {}4 $ curl ’http :// localhost :4567/ witaj?imie=Stanislaw&nazwisko=Polak’5 Pierwsza trasa6 hasz ’params ’ zawiera: {"imie"=>"Stanislaw", "nazwisko"=>"Polak"}7 $ curl http :// localhost :4567/ witaj/Swiecie8 Trzecia trasa9 hasz ’params ’ zawiera: {"splat"=>[], "captures"=>["Swiecie"], "nazwa"=>"Swiecie"}
10 $ curl ’http :// localhost :4567/ witaj/Swiecie?imie=Stanislaw&nazwisko=Polak’11 Trzecia trasa12 hasz ’params ’ zawiera: {"imie"=>"Stanislaw", "nazwisko"=>"Polak", "splat"=>[], "captures"=>["Swiecie"],
"nazwa"=>"Swiecie"}
Dr inż. Stanisław Polak 118
Podstawy języka dziedzinowego „Sinatra”
SzablonUżycie szablonu ERB
1 get ’/witaj ’ do2 erb(:witaj) #Renderuj szablon ’views/witaj.erb ’
3 end
skrypt.rb
1 <%# To jest komentarz %>2 <%# Poniżej jest skryptlet %>3 <% 3. downto (0) do |i| %>4 <%# Poniżej jest wyrażenie %>5 <%= i %>,6 <% end %>7 Start
views/witaj.erb
1 $ curl http :// localhost :4567/ witaj2 3,3 2,4 1,5 0,6 Start
Wykonywanie żądania
Dr inż. Stanisław Polak 120
Mat
eriał
ydla
studen
tów
Infor
mat
yki wyd
ziału
IET
AGHw
Krako
wieNotatki
Notatki
Podstawy języka dziedzinowego „Sinatra”
Szablon „inline”
1 require ’sinatra ’23 get ’/witaj ’ do4 erb(:witaj)
5 end6 __END__78 @@witaj9 <%# To jest komentarz %>
10 <%# Poniżej jest skryptlet %>11 <% 3. downto (0) do |i| %>12 <%# Poniżej jest wyrażenie %>13 <%= i %>,14 <% end %>15 Start
skrypt.rb
Dr inż. Stanisław Polak 121
Podstawy języka dziedzinowego „Sinatra”
Szablon częściowy
1 require ’sinatra ’23 get ’/’ do4 erb(:index)5 end
skrypt.rb
1 <%= erb(:witaj) %>2 <%= erb(: swiecie) %>
views/index.erb
1 Witaj
views/witaj.erb
1 Świecie
views/swiecie.erb
1 $ curl http :// localhost :4567/2 Witaj3 Świecie
Wykonywanie żądania
Dr inż. Stanisław Polak 122
Notatki
Notatki
Podstawy języka dziedzinowego „Sinatra”
Układ
1 <html>2 <head>3 <title>Aplikacja Sinatra </title>4 </head>5 <body>6 <h1>Aplikacja Sinatra </h1>7 <!-- początek wstawki szablonu -->8 <%= yield %>9 <!-- koniec wstawki szablonu -->
10 </body>11 </html>
views/layout.erb
1 <% 3. downto (0) do |i| %>2 <%= i %>,3 <% end %>4 Start
views/witaj.erb
1 $ curl http :// localhost :4567/ witaj2 <html >3 <head >4 <title >Aplikacja Sinatra </title >5 </head >6 <body >7 <h1>Aplikacja Sinatra </h1>8 <!-- początek wstawki szablonu -->9 3,
10 2,11 1,12 0,13 Start1415 <!-- koniec wstawki szablonu -->16 </body >17 </html >
Wykonywanie żądania
Dr inż. Stanisław Polak 123
Podstawy języka dziedzinowego „Sinatra”
Dostęp do zmiennych z poziomu szablonu
1 require ’sinatra ’23 get ’/witaj ’ do4 @tekst1 = "Witaj" #Zmienna instancyjna jest dostępna z poziomu szablonu5 tekst2 = "Świecie" #Zwykła zmienna nie jest dostępna z poziomu szablonu6 erb(:witaj , :locals => {:tekst3 => tekst2 }) #Definiowanie , dla szablonu ’witaj ’, zmiennej lokalnej ’
tekst3 ’7 end
skrypt.rb
1 <%= @tekst1 %> <%= tekst3 %>
views/witaj.erb
1 $ curl http :// localhost :4567/ witaj2 Witaj Świecie
Wykonywanie żądania
Dr inż. Stanisław Polak 124
Notatki
Notatki
Podstawy języka dziedzinowego „Sinatra”
PrzykładPrzetwarzanie zawartości formularza
1 require ’sinatra ’23 get ’/formularz ’ do4 erb :formularz5 end67 post ’/formularz ’ do8 "Pole ’nazwa ’ zawiera napis ’#{params[:nazwa]}’"9 end
skrypt.rb
1 <form action="/formularz" method="post">2 <input type="text" name="nazwa">3 <input type="submit">4 </form>
views/formularz.erb
Dr inż. Stanisław Polak 125
Podstawy języka dziedzinowego „Sinatra”
REST API w Sinatra
1 require ’sinatra ’23 use Rack::MethodOverride45 get ’/formularz ’ do6 erb :formularz7 end89 delete ’/products /:id’ do
10 "Usuwam produkt o id=#{ params[’id ’]}"11 end
skrypt.rb
1 <form method="POST" action="/products /1">2 <input type="hidden" name=" method" value="DELETE">3 <input type="submit">4 </form>
views/formularz.erb
Dr inż. Stanisław Polak 126
Notatki
Notatki
Podstawy języka dziedzinowego „Sinatra”
Trasowanie plików statycznych
1 <!DOCTYPE html>2 <html>3 <head>4 <meta charset="UTF -8">5 <link rel="stylesheet" href="/css/style.css">6 <title>Aplikacja Sinatra </title>7 </head>8 <body>9 <h1>Aplikacja Sinatra </h1>
10 <%= yield %>11 </body>12 </html>
views/layout.erb
1 h1 {color: red}
public/css/style.css
Dr inż. Stanisław Polak 127
Framework Ruby on Rails
Plan prezentacji
Wstęp
Przykład tworzenia aplikacji
Kontroler
Model
Widok
Lokalizacja i umiędzynarodowienie
Uwierzytelnianie i autoryzacja
Dr inż. Stanisław Polak 128
Notatki
Notatki
Framework Ruby on Rails Wstęp
Instalacja Ruby on RailsPrzykład dla Ubuntu
1 # Instalacja ’Node.js ’2 $ sudo apt -get install nodejs3 # Instalacja ’yarn ’4 $ curl -sS https ://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt -key add -5 $ echo "deb https ://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list6 $ sudo apt -get update && sudo apt -get install yarn7 # Instalacja ’Ruby on Rails ’8 $ gem install rails
Instalacja
1 $ gem update rails
Aktualizacja
Dr inż. Stanisław Polak 131
Framework Ruby on Rails Wstęp
Serwer aplikacji „Phusion Passenger” (mod passenger)
I Serwer aplikacji dla Ruby, Python, Node.js oraz MeteorI Obsługuje żądania HTTP, zarządza procesami oraz zasobami, a także umożliwia administrowanie,
monitorowanie i diagnozowanie problemówI Może działać jako samodzielny serwer aplikacji oraz serwer WWWI Posiada możliwość integracji z serwerami WWW: „Apache” oraz „nginx”
Źródło: https://www.phusionpassenger.com/
1 $ gem install passenger2 $ rvmsudo passenger -config validate -install3 $ cd katalog_z_aplikacją_RoR4 $ passenger start --daemonize
Przykład dla Linux-a / macOS-a
Dr inż. Stanisław Polak 132
Mat
eriał
ydla
studen
tów
Infor
mat
yki wyd
ziału
IET
AGHw
Krako
wieNotatki
Notatki
Framework Ruby on Rails Wstęp
Typowe żądanie
Przykładowy adres strony: http://www.przyklad.pl/ students / 1 / edit
Źródło: http://www.sitepoint.com/getting-started-with-mvc/
Dr inż. Stanisław Polak 133
Framework Ruby on Rails Wstęp Konwencje nazewnicze
Konwencje dla tabel bazy danych i modeli
Nazwa tabeli Nazwa (klasy) modelu Nazwa pliku z modelemstudents Student student.rbuniversity employees UniversityEmployee university employee.rb
Tabela łącznikowa: students teachers
id faculty id firstName lastName1 4 Jan Kowalski. . . . . . . . . . . .
Tablica: students
id name. . . . . .4 Informatyki. . . . . .
Tablica: faculties
1 class Student < ApplicationRecord2 ...3 end
app/models/student.rb
Dr inż. Stanisław Polak 134
Notatki
Notatki
Framework Ruby on Rails Wstęp Konwencje nazewnicze
Konwencje dla kontrolerów
1 class StudentsController < ApplicationController23 # http :// www.przyklad.pl/students4 def index5 ...6 end78 # http :// www.przyklad.pl/students /1/ edit9 def edit
10 ...11 end1213 ...14 end
app/controllers/students controller.rb
Dr inż. Stanisław Polak 135
Framework Ruby on Rails Wstęp Konwencje nazewnicze
Konwencje dla widoków
1 <h1>List of students </h1>2 <table >3 ...4 <% @students.each do |student| %>5 <td ><%= student.lastName %></td >6 ...7 <% end %>8 ...9 </table >
app/views/students/index.html.erb
1 <h1>Editing Student </h1 >2 <%= form_with :scope :student , url: student_path(@student),
method: :patch do |f| %>3 ...4 <% end %>
app/views/students/edit.html.erb
1 class StudentsController < ApplicationController23 def index4 ...5 end6 ...7 def edit8 ...9 end
10 ...11 end
app/controllers/students controller.rb
Dr inż. Stanisław Polak 136
Notatki
Notatki
Framework Ruby on Rails Wstęp Konwencje nazewnicze
Przykład zastosowania
Adres strony: http://www.przyklad.pl/students/1/edit
1 class StudentsController < ApplicationController2 ...3 def edit4 ...5 end6 ...7 end
app/controllers/students controller.rb
1 class Student < ApplicationRecord2 ...3 end
app/models/student.rb
id faculty id firstName lastName
1 . . . . . . . . .
Tablica: students
1 <h1>Editing Student </h1 >2 <%= form_with :scope :student , url: student_path(@student), method: :patch do |f| %>3 ...4 <% end %>
app/views/students/edit.html.erb
Dr inż. Stanisław Polak 137
Framework Ruby on Rails Wstęp Narzędzia wiersza poleceń
Program „rails”
1 $ rails2 Usage: rails COMMAND [ARGS]34 The most common rails commands are:5 generate Generate new code (short -cut alias: "g")6 console Start the Rails console (short -cut alias: "c")7 server Start the Rails server (short -cut alias: "s")8 test Run tests (short -cut alias: "t")9 dbconsole Start a console for the database specified in config/database.yml
10 (short -cut alias: "db")11 new Create a new Rails application. "rails new my_app" creates a12 new application called MyApp in "./ my_app"1314 All commands can be run with -h (or --help) for more information.1516 In addition to those commands , there are:17 ...
Dr inż. Stanisław Polak 138
Notatki
Notatki
Framework Ruby on Rails Wstęp Narzędzia wiersza poleceń
Program „rake”
1 $ rake --tasks2 # rails --tasks # Możliwość dostępna w RoR 5.03 ...4 rake db:create # Create the database from DATABASE_URL or config/database.yml
for the current Rails.env (use db:create:all to create all dbs in the config)5 rake db:drop # Drops the database using DATABASE_URL or the current Rails.env
(use db:drop:all to drop all databases )6 rake db:fixtures:load # Load fixtures into the current environment ’s database7 rake db:migrate # Migrate the database (options: VERSION=x, VERBOSE=false , SCOPE
=blog)8 rake db:rollback # Rolls the schema back to the previous version (specify steps w
/ STEP=n)9 rake db:schema:dump # Create a db/schema.rb file that can be portably used against
any DB supported by AR10 rake db:schema:load # Load a schema.rb file into the database11 rake db:seed # Load the seed data from db/seeds.rb12 rake db:setup # Create the database , load the schema , and initialize with the
seed data (use db:reset to also drop the db first)13 rake db:structure:dump # Dump the database structure to db/ structure.sql14 rake routes # Print out all defined routes in match order , with names15 rake test # Runs test:units , test:functionals , test: integration together16 ...
Dr inż. Stanisław Polak 139
Framework Ruby on Rails Wstęp Narzędzia wiersza poleceń
Program „bundle”
1 source ’https :// rubygems.org’23 # Bundle edge Rails instead: gem ’rails ’, github: ’rails/rails
’4 gem ’rails ’, ’4.2.5 ’5 # Use sqlite3 as the database for Active Record6 gem ’sqlite3 ’7 # Use SCSS for stylesheets8 gem ’sass -rails ’, ’~> 5.0’9 # Use Uglifier as compressor for JavaScript assets
10 gem ’uglifier ’, ’>= 1.3.0’11 ...
Gemfile
1 GEM2 remote: https :// rubygems.org/3 specs:4 actionmailer (4.2.5)5 actionpack (= 4.2.5)6 actionview (= 4.2.5)7 activejob (= 4.2.5)8 mail (~> 2.5, >= 2.5.4)9 rails -dom -testing (~> 1.0, >= 1.0.5)
10 actionpack (4.2.5)11 ...
Gemfile.lock
1 $ bundle install2 Fetching gem metadata from https :// rubygems.org /...........3 Fetching version metadata from https :// rubygems.org /...4 Fetching dependency metadata from https :// rubygems.org/..5 Resolving dependencies .....6 Using rake 10.4.27 Using i18n 0.7.08 Using json 1.8.39 Using minitest 5.8.3
10 Using thread_safe 0.3.511 Using builder 3.2.212 Using erubis 2.7.013 Using mini_portile2 2.0.014 Using rack 1.6.415 ...16 Using web -console 2.2.117 Using turbolinks 2.5.318 Bundle complete! 12 Gemfile dependencies , 54 gems now
installed.19 Use ‘bundle show [gemname]‘ to see where a bundled gem is
installed.
Instalowanie zależności
Dr inż. Stanisław Polak 140
Notatki
Notatki
Framework Ruby on Rails Wstęp Narzędzia wiersza poleceń
Program „spring”1 $ spring --help2 Version: 1.7.234 Usage: spring COMMAND [ARGS]56 Commands for spring itself:78 binstub Generate spring based binstubs. Use --all to generate a binstub for all known commands. Use --
remove to revert.9 help Print available commands.
10 server Explicitly start a Spring server in the foreground11 status Show current status.12 stop Stop all spring processes for this project.1314 Commands for your application:1516 rails Run a rails command. The following sub commands will use spring: console , runner , generate ,
destroy , test.17 rake Runs the rake command
Dr inż. Stanisław Polak 141
Framework Ruby on Rails Wstęp Testy
TestowanieStruktura katalogów
1 $ ls test2 application_system_test_case.rb fixtures integration models test_helper.rb3 controllers helpers mailers system
Dr inż. Stanisław Polak 144
Mat
eriał
ydla
studen
tów
Infor
mat
yki wyd
ziału
IET
AGHw
Krako
wieNotatki
Notatki
Framework Ruby on Rails Przykład tworzenia aplikacji
Pierwsza aplikacjaZałożenia
I Wyświetlamy dane użytkowników: imię oraz nazwiskoI Dane są umieszczone w kodzie źródłowym kontrolera
Dr inż. Stanisław Polak 145
Framework Ruby on Rails Przykład tworzenia aplikacji
Tworzenie szkieletu aplikacjiOgólna struktura katalogu z kodem aplikacji
1 $ rails new firstApp
firstApp
app
bin
config
config.ru
db
Gemfile
Gemfile.lock
lib
log
package.json
public
Rakefile
README.rdoc
storage
test
tmp
vendor
Dr inż. Stanisław Polak 146
Notatki
Notatki
Framework Ruby on Rails Przykład tworzenia aplikacji
Tworzenie aplikacji
1 $ cd firstApp2 $ bin/rails generate controller users index3 create app/controllers/users_controller.rb4 route get ’users/index’5 invoke erb6 create app/views/users7 create app/views/users/index.html.erb8 invoke test_unit9 create test/controllers/users_controller_test.rb
10 invoke helper11 create app/helpers/users_helper.rb12 invoke test_unit13 invoke assets14 invoke coffee15 create app/assets/javascripts/users.coffee16 invoke scss17 create app/assets/stylesheets/users.scss18 $ bin/rails server19 => Booting Puma20 => Rails 5.0.0 application starting in development on http ://
localhost :300021 => Run ‘rails server -h‘ for more startup options22 Puma starting in single mode ...23 * Version 3.4.0 (ruby 2.3.1 - p112), codename: Owl Bowl Brawl24 * Min threads: 5, max threads: 525 * Environment: development26 * Listening on tcp:// localhost :300027 Use Ctrl -C to stop
1 class UsersController < ApplicationController2 def index3 @@user1 = ’Joanna Wiśniewska ’4 @user2 = ’Jan Kowalski ’5 user3 = ’Anna Nowak’6 end7 end
app/controllers/users controller.rb
1 <h1>Lista użytkowników</h1>2 <% if defined? @@user1 %>3 <%= @@user1 %>4 <% end %>56 <% if defined? @user2 %>7 <%= @user2 %>8 <% end %>9
10 <% if defined? user3 %>11 <%= user3 %>12 <% end %>
app/views/users/in-dex.html.erb
Dr inż. Stanisław Polak 147
Framework Ruby on Rails Kontroler
Parametry
1 class UsersController < ApplicationController2 ...34 def show56 # Dla URL ’http :// localhost :3000/ users /1’,7 # tablica ’params ’ zawiera: {" action "=>" show", " controller "=>" users", "id "= >"1"}8 id = params [:id] #19 nazwa_kontrolera = controller_name # ’users ’
10 nazwa_akcji = action_name # ’show ’11 end12 end
app/controllers/users controller.rb
Dr inż. Stanisław Polak 148
Notatki
Notatki
Framework Ruby on Rails Kontroler
Tworzenie odpowiedzi HTTP
I render
I redirect to
I head
1 class UsersController < ApplicationController2 def index3 # Renderowanie niczego4 render nothing: true #Kod statusu: 2005 render nothing: true , status: 404 #Kod statusu: 4046 # Renderowanie szablonu dla akcji7 render "edit"8 render :edit9 # Renderowanie szablonu dla akcji z innego kontrolera
10 render ’products/show’11 render :template => ’products/show’12 # Renderowanie dowolnego pliku13 render :file => "/u/apps/warehouse_app/current/app/views/products/show"14 # Renderowanie typu "inline"15 render :inline => "<% users.each do |u| %><p><%= u.nazwisko %><p><% end %>"16 render :inline => "xml.p {’Horrid coding practice!’}", :type => :builder17 render :plain => "OK" # Renderowanie tekstu , typ zawartości: text/plain18 render :html => "OK" # Renderowanie tekstu , typ zawartości: text/html19 render :body => "OK" # Renderowanie tekstu , typ zawartości nie jest ustawiany20 render :json => @user # Renderowanie JSON21 render :xml => @user # Renderowanie XML22 render :js => "alert(’Hello Rails ’);" # Renderowanie JS23 end24 end
app/controllers/users controller.rb
Dr inż. Stanisław Polak 149
Framework Ruby on Rails Kontroler
Filtry
TypyI wstępny — before actionI końcowy — after actionI okalający — around action
ArgumentyI Odniesienie do metody (symbol)I Klasa zewnętrznaI Metoda inline (proc)
1 class UsersController < ApplicationController2 before_action :set_user , only: [:show , :edit , :update , :destroy]3 ...4 # Use callbacks to share common setup or constraints between actions.5 def set_user6 @user = User.find(params [:id])7 end8 end
Kontroler
Dr inż. Stanisław Polak 150
Notatki
Notatki
Framework Ruby on Rails Kontroler
Przykłady użycia filtra okalającego
1 class ApplicationController < Application23 around_action :catch_exceptions45 private67 def catch_exceptions8 yield9 rescue => exception
10 logger.debug "Caught exception! #{ exception}"11 raise12 end1314 end
1 around_action do |controller , action|23 #Plik logów - log/ development .log4 logger.debug "before #{ controller.action_name}"5 action.call6 logger.debug "after #{ controller.action_name}"7 end
Dr inż. Stanisław Polak 151
Framework Ruby on Rails Kontroler
Sesja
I CookieStoreI CacheStoreI ActiveRecordStoreI MemCacheStore
1 class UsersController < ApplicationController2 def index3 if session.has_key ?(: licznik)4 session [: licznik] += 15 else6 session[:licznik] = 17 end8 if session [: licznik] > 39 session[:licznik] = nil
10 end11 end12 end
app/controllers/users controller.rb
1 <%= session[:licznik] %>
app/views/users/index.html.erb
Wynik dla kolejnych żądań123
1
Dr inż. Stanisław Polak 152
Notatki
Notatki
Framework Ruby on Rails Kontroler
Flash
1 class UsersController < ApplicationController2 def index3 if session.has_key ?(: licznik)4 session [: licznik] += 15 else6 session [: licznik] = 17 end8 if session [: licznik] == 19 flash[:komunikat] = "Witaj"
10 elsif session [: licznik] > 311 session [: licznik] = nil12 end13 end14 end
app/controllers/users controller.rb
1 <%= session [: licznik] %>2 <%= flash[:komunikat] %>
app/views/users/index.html.erb
Wynik dla kolejnych żądań
1 Witaj2 Witaj3
1 Witaj
Dr inż. Stanisław Polak 153
Framework Ruby on Rails Kontroler
Ciasteczka
1 class UsersController < ApplicationController2 def index3 if cookies.has_key ?(: licznik)4 cookies [: licznik] = cookies [: licznik ].to_i + 15 else6 cookies [: licznik] = 17 end8 if cookies [: licznik] > 39 cookies.delete (: licznik)
10 end11 end12 end
app/controllers/users controller.rb
1 <%= cookies [: licznik] %>
app/views/users/index.html.erb
Wynik dla kolejnych żądań
123
1
Dr inż. Stanisław Polak 154
Mat
eriał
ydla
studen
tów
Infor
mat
yki wyd
ziału
IET
AGHw
Krako
wieNotatki
Notatki
Framework Ruby on Rails Kontroler
Uwierzytelnianie HTTP
Podstawowe
1 class UsersController < ApplicationController2 http_basic_authenticate_with name: "abc", password
: "hasło", except: :index34 def index5 ...6 end78 def show9 ...
10 end11 end
Przez skrót
1 class UsersController < ApplicationController2 USERS = { "abc" => "hasło" }34 before_action :authenticate56 private78 def authenticate9 authenticate_or_request_with_http_digest do |
username|10 USERS[username]11 end12 end13 end
Dr inż. Stanisław Polak 155
Framework Ruby on Rails Kontroler
RoutingCRUD, typy żądań i akcje
1 Users:: Application.routes.draw do2 resources :users3 end
config/routes.rb
ŻądanieHTTP
Ścieżka Akcja Cel użycia
GET /users index wyświetlenie listy wszystkich użytkownikówGET /users/new new zwrócenie formularza HTML do tworzenia użytkow-
nikaPOST /users create utworzenie nowego użytkownikaGET /users/:id show wyświetlenie konkretnego użytkownikaGET /users/:id/edit edit zwrócenie formularza HTML do edycji użytkownikaPATCH /PUT
/users/:id update aktualizacja konkretnego użytkownika
DELETE /users/:id destroy usunięcie konkretnego użytkownika
Dr inż. Stanisław Polak 156
Notatki
Notatki
Framework Ruby on Rails Kontroler
RoutingAdresy URL i ścieżki dostępu
Pomocnik Wynikusers path /usersusers url http://localhost:3000/usersnew user path /users/newedit user path(10) /users/10/edituser path(10) /users/10
Dr inż. Stanisław Polak 157
Framework Ruby on Rails Kontroler Testy funkcjonalne
Przykładowa aplikacjaGenerowanie szkieletu aplikacji oraz konfiguracja
1 $ rails new secondApp2 $ cd secondApp3 $ vim config/routes.rb
1 Rails.application.routes.draw do2 resources :users3 end
config/routes.rb
Dr inż. Stanisław Polak 160
Notatki
Notatki
Framework Ruby on Rails Kontroler Testy funkcjonalne
Przykładowa aplikacjaKontroler oraz widok
1 $ bin/rails generate controller users2 $ vim app/controllers/users_controller.rb3 $ vim app/views/users/index.html.erb
1 class UsersController < ApplicationController2 @@user1 = nil3 @@user2 = ’Anna Nowak’4 ## #############################5 def index6 @user1 = @@user17 @user2 = @@user28 end9
10 def new11 @@user1 = ’Jan Kowalski ’12 redirect_to users_path13 end14 end
app/controllers/users controller.rb
1 <ul>2 <% if defined? @user1 %>3 <li ><%= @user1 %>4 <% end %>5 <% if defined? @user2 %>6 <li ><%= @user2 %>7 <% end %>8 </ul >
app/views/users/index.html.erb
Dr inż. Stanisław Polak 161
Framework Ruby on Rails Kontroler Testy funkcjonalne
Przykładowe test funkcjonalne dla kontrolera
1 $ vim test/controllers/users_controller_test.rb
2 $ bin/rails test test/controllers/users_controller_test.rb
3 Running via Spring preloader in process454
4 Run options: --seed 2783356 # Running:78 .9
10 Finished in 0.781415s, 1.2797 runs/s,14.0770 assertions/s.
11 1 runs , 11 assertions , 0 failures , 0errors , 0 skips
Oznaczenia
„.” test został zaliczony
„F” test nie został zaliczony
1 require ’test_helper ’23 class UsersControllerTest < ActionDispatch ::
IntegrationTest4 test ’akcja index przed i po dodaniu rekordu ’ do5 get users_url # akcja ’index ’6 assert response :success7 assert match ’Nowak’, @response.body8 assert no match ’Kowalski ’, @response.body9 ## #################
10 get new_user_url # akcja ’add ’11 assert response :found12 ## #################13 get users_url # akcja ’index ’14 assert response :success15 assert match ’Nowak’, @response.body16 assert match ’Kowalski ’, @response.body17 end18 #Powyższy fragment jest równoważny:19 # def test_akcja_index_przed_i_po_dodaniu_rekordu20 # ...21 # end22 end
test test/controllers/users controller test.rb
Dr inż. Stanisław Polak 162
Notatki
Notatki
Framework Ruby on Rails Model Podstawy
Nadpisywanie konwencji nazewniczych
1 class User < ApplicationRecord2 self.table_name = "uzytkownik" #nazwa tabeli BD3 self.primary_key = "uzytkownik_id" #nazwa kolumny zawierającej klucz główny4 end
Dr inż. Stanisław Polak 163
Framework Ruby on Rails Model Podstawy
Wstawianie danych do BD
1 #Pierwszy sposób - w oparciu o hasz2 user = User.new(imię: "Jan", nazwisko: "Kowalski", pensja: 2000)3 user.save4 #lub5 user = User.create(imię: "Jan", nazwisko: "Kowalski", pensja: 2000)67 #Drugi sposób - w oparciu o blok8 user = User.create do |u|9 u.imię = "Jan"
10 u.nazwisko = "Kowalski"11 u.pensja = 200012 end13 #lub14 user = User.new do |u|15 u.imię = "Jan"16 u.nazwisko = "Kowalski"17 u.pensja = 200018 end19 user.save2021 #Trzeci sposób - poprzez "ręczne" ustawienie atrybutów22 user = User.new23 user.imię = "Jan"24 user.nazwisko = "Kowalski"25 user.pensja = 200026 user.save
Kontroler
Dr inż. Stanisław Polak 164
Notatki
Notatki
Framework Ruby on Rails Model Podstawy
Pobieranie danych z BD
1 #Zwróć kolekcję ze wszystkimi uż ytkownikami (wszystkie rekordy)2 users = User.all34 #Zwróć pierwszego użytkownika (pierwszy rekord)5 user = User.first67 #Odszukaj pierwszego użytkownika o imieniu ’Jan ’ i zwróć go8 jan = User.find_by(imię: ’Jan’)9
10 #Odszukaj wszystkich Janów Kowalskich i posortuj wynik szukania w odwrotnej kolejności według datyutworzenia rekordu
11 users = User.where(imię: ’Jan’, nazwisko: ’Kowalski ’).order(’created_at DESC’)
Kontroler
Dr inż. Stanisław Polak 165
Framework Ruby on Rails Model Podstawy
Aktualizacja danych w BD
1 #Pierwszy sposób2 user = User.find_by(imię: ’Jan’)3 user.imię=’Jerzy’4 user.save56 #Drugi sposób7 user = User.find_by(imię: ’Jan’)8 user.update(imię: ’Jerzy’)
Kontroler
Dr inż. Stanisław Polak 166
Mat
eriał
ydla
studen
tów
Infor
mat
yki wyd
ziału
IET
AGHw
Krako
wieNotatki
Notatki
Framework Ruby on Rails Model Podstawy
Usuwanie danych z BD
1 user = User.find_by(id:1)2 user.destroy
Kontroler
Dr inż. Stanisław Polak 167
Framework Ruby on Rails Model Podstawy
Silne parametry
1 class UserController < ApplicationController2 # http :// localhost :3000/ user/signup?user[name ]= ow3ned&user[
admin ]=13 def signup4 p params [:user] # {: name => "ow3ned" :admin => true}56 # Utworzenie nowego rekordu , który może być (później)
wstawiony do bazy danych7 @user = User.new(params [:user])8 #To spowoduje wygenerowanie wyjątku ActiveModel ::
ForbiddenAttributes9 #gdyż metoda używa ,,masowego przypisania ’’ (ang. ,,mass
assignment ’’),10 #bez bez wyraźnego kroku zezwolenia .1112 @user = User.new(user_params) #Tutaj wyjątku nie będzie13 end1415 def user_params16 params.require(:user).permit(:imię, :nazwisko , :pensja)17 end18 end
app/controllers/user controller.rb
1 $ rails console2 params = ActionController :: Parameters.new({3 user: {4 imię: ’Jan’,5 nazwisko: ’Kowalski ’,6 pensja: 2222,7 }8 })9 params
10 =>{"user"=>{"imię"=>"Jan", "nazwisko"=>"Kowalski", "pensja"= >2222}}
11 params [:user]12 => {"imię"=>"Jan", "nazwisko"=>"Kowalski", "pensja"= >2222}13 params.require(:user)14 => {"imię"=>"Jan", "nazwisko"=>"Kowalski", "pensja"= >2222}15 params.require(: nazwisko)16 ActionController :: ParameterMissing: param is missing or the
value is empty: nazwisko17 params [:user].permit(:imię)18 => {"imię"=>"Jan"}19 params [:user].permit(:imię,:nazwisko)20 => {"imię"=>"Jan", "nazwisko"=>"Kowalski"}21 params [:user].permit(: pesel)22 => {}
Dr inż. Stanisław Polak 168
Notatki
Notatki
Framework Ruby on Rails Model Migracje
Anatomia migracji
1 class CreateUsers < ActiveRecord::Migration[5.1]2 # Wykonanie poniższej metody powoduje komenda: bin/rake db:migrate3 #Zadanie ’db:migrate ’ uruchamia również zadanie ’db:schema:dump ’4 def up5 create table :users do |t|6 #kolumna ’id’ zostanie utworzona automatycznie7 t.string :imię8 t.string :nazwisko9 t.decimal :pensja
10 t.timestamps # utworzenie kolumn: ’created_at ’, ’updated_at ’11 end12 end1314 # Wykonanie poniższej metody powoduje komenda: bin/rake db:rollback15 def down16 drop_table users17 end18 end
db/migrate/YYYYMMDDHHMMSS create users.rb
Dr inż. Stanisław Polak 170
Framework Ruby on Rails Model Migracje
Migracje odwracalne
1 class CreateUsers < ActiveRecord :: Migration [5.1]2 def change3 create_table :users do |t|4 t.string :imię5 t.string :nazwisko6 t.decimal :pensja7 t.timestamps8 end9 end
10 end
Dr inż. Stanisław Polak 171
Notatki
Notatki
Framework Ruby on Rails Model Migracje
Tworzenie samodzielnej migracji
1 $ #bin/rails generate migration AddFieldsToUsers2 $ #bin/rails generate migration AddFieldsToUsers adres:string3 $ #bin/rails generate migration RemoveFieldsFromUsers pensja
1 class AddFieldsToUsers < ActiveRecord :: Migration [5.1]2 def change3 add column :users, :adres, :string4 end5 end
YYYYMMDDHHMMSS add fields to users.rb
1 class RemoveFieldsFromUsers < ActiveRecord :: Migration [5.1]2 def change3 remove_column :users , :pensja , :string4 end5 end
YYYYMMDDHHMMSS remove fields from users.rb
Dr inż. Stanisław Polak 172
Framework Ruby on Rails Model Migracje
Uruchamianie migracji
1 $ ls db/migrate/2 20140213155816 _create_users.rb3 20140214153539 _add_fields_to_users.rb4 20140214153735 _remove_fields_from_users.rb
1 $ bin/rake db:migrate VERSION=201402141535392 == CreateUsers: migrating ====================================================3 -- create_table (: users)4 -> 0.0044s5 == CreateUsers: migrated (0.0045s) ===========================================67 == AddFieldsToUsers: migrating ===============================================8 -- add_column (:users , :adres , :string)9 -> 0.0086s
10 == AddFieldsToUsers: migrated (0.0087s) ======================================11 $ bin/rake db:migrate VERSION=2014021315581612 == AddFieldsToUsers: reverting ===============================================13 -- remove_column (:users , :adres , :string)14 -> 0.0079s15 == AddFieldsToUsers: reverted (0.0194s) ======================================
Dr inż. Stanisław Polak 173
Notatki
Notatki
Framework Ruby on Rails Model Asocjacje
Po co asocjacje?
Bez asocjacji
1 class Faculty < ApplicationRecord2 end34 class Student < ApplicationRecord5 end
Modele
1 @faculty = Faculty.create(name: "Informatyki")2 # Tworzenie nowego studenta wydziału Informatyki3 @student = Student.create(faculty_id: @faculty.id,firstName: "
Jan",lastName: "Kowalski")4 #Wyświetlenie , dla utworzonego studenta , nazwy wydziału5 puts Faculty.where(id: @student.faculty_id).first.name #Wyś
wietli: Informatyki6 #lub7 puts Faculty.find(@student.faculty_id).name #Wyświetli:
Informatyki8 #Usuwanie wydziału oraz studentów9 @students = Student.where(faculty_id: @faculty.id)
10 @students.each do |student|11 student.destroy12 end13 @faculty.destroy
Kontroler
Z asocjacjami
1 class Faculty < ApplicationRecord2 has_many :students , dependent: :destroy3 end45 class Student < ApplicationRecord6 belongs_to :faculty7 end
Modele
1 @faculty = Faculty.create(name: "Informatyki")2 #Tworzenie nowego studenta wydziału Informatyki3 @student = @faculty.students.create(firstName: "Jan",lastName:
"Kowalski")4 #Wyświetlenie , dla utworzonego studenta , nazwy wydziału5 puts @student.faculty.name #Wyświetli: Informatyki6 #Usuwanie wydziału oraz studentów7 @faculty.destroy
Kontroler
Dr inż. Stanisław Polak 174
Framework Ruby on Rails Model Asocjacje
Asocjacja „belongs to”
1 class Student < ApplicationRecord2 belongs_to :faculty3 end
Model
1 class CreateStudents < ActiveRecord :: Migration [5.1]2 def change3 create_table :students do |t|4 t.belongs_to :faculty5 t.string : firstName6 t.string : lastName7 end89 create_table :faculties do |t|
10 t.string :name11 end12 end13 end
Migracja
students
Model: Studentbelongs to: faculty
id: integer
faculty id: integer
firstName: string
lastName: string
faculties
Model: Faculty
id: integer
name: string
Dr inż. Stanisław Polak 176
Notatki
Notatki
Framework Ruby on Rails Model Asocjacje
Asocjacja „has one”
1 class Student < ApplicationRecord2 has_one :locker3 end
Model
1 class CreateStudents < ActiveRecord :: Migration [5.1]2 def change3 create_table :students do |t|4 t.string : firstName5 t.string : lastName6 end78 create_table :lockers do |t|9 t.belongs_to :student
10 t.integer :number11 end12 end13 end
Migracja
students
Model: Studenthas one: locker
id: integer
firstName: string
lastName: string
lockers
Model: Locker
id: integer
student id: integer
number: integer
Dr inż. Stanisław Polak 177
Framework Ruby on Rails Model Asocjacje
Asocjacja „has many”
1 class Faculty < ApplicationRecord2 has_many :students3 end
Model
1 class CreateFaculties < ActiveRecord :: Migration [5.1]2 def change3 create_table :faculties do |t|4 t.string :name5 end67 create_table :students do |t|8 t.belongs_to :faculty9 t.string :firstName
10 t.string :lastName11 end12 end13 end
Migracja
faculties
Model: Facultyhas many: students
id: integer
name: string
students
Model: Student
id: integer
faculty id: integer
firstName: string
lastName: string
Dr inż. Stanisław Polak 178
Mat
eriał
ydla
studen
tów
Infor
mat
yki wyd
ziału
IET
AGHw
Krako
wieNotatki
Notatki
Framework Ruby on Rails Model Asocjacje
Asocjacja „has many :through”
1 class Student < ApplicationRecord2 has_many :classes3 has_many :teachers , through: classes4 end56 class Class < ApplicationRecord7 belongs_to :student8 belongs_to :teacher9 end
1011 class Teacher < ApplicationRecord12 has_many :classes13 has_many :students , through: classes14 end
Model
1 class CreateClasses < ActiveRecord :: Migration [5.1]2 def change3 create_table :students do |t|4 t.string :firstName5 t.string :lastName6 end78 create_table :teachers do |t|9 t.string :name
10 end1112 create_table :classes do |t|13 t.belongs_to :student14 t.belongs_to :teacher15 t.datetime :term16 end17 end18 end
Migracja
students
Model: Studenthas many :classeshas many :teachers,:through=> :classes
id: integer
firstName: string
lastName: string
classes
Model: Classbelongs to :studentbelongs to :teacher
id: integer
student id: integer
teacher id: integer
term: datetime
teachers
Model: Teacherhas many :classeshas many :students,:through=> :classes
id: integer
name: string
Dr inż. Stanisław Polak 179
Framework Ruby on Rails Model Asocjacje
Asocjacja „has one :through”
1 class Student < ApplicationRecord2 has_one :account3 has_one :account_history , through: :account4 end56 class Account < ApplicationRecord7 belongs_to :student8 has_one :account_history9 end
1011 class AccountHistory < ApplicationRecord12 belongs_to :account13 end
Model
1 class CreateAccountHistories < ActiveRecord :: Migration [5.1]2 def change3 create_table :students do |t|4 t.string :firstName5 t.string :lastName6 end78 create_table :accounts do |t|9 t.belongs_to :student
10 t.string :account_number11 end1213 create_table :account_histories do |t|14 t.belongs_to :account15 t.integer :return_book_punctuality_rating16 end17 end18 end
Migracja
students
Model: Studenthas one :accounthas one :account history, :through=> :account
id: integer
firstName: string
lastName: string
accounts
Model: Accountbelongs to :studenthas one :account history
id: integer
student id: integer
account number: string
account histories
Model: AccountHistorybelongs to :account
id: integer
account id: integer
return book punctuality rating: integer
Dr inż. Stanisław Polak 180
Notatki
Notatki
Framework Ruby on Rails Model Asocjacje
Asocjacja „has and belongs to many”
1 class Student < ApplicationRecord2 has_and_belongs_to_many :teachers3 end45 class Teacher < ApplicationRecord6 has_and_belongs_to_many :students7 end
Model
1 class CreateStudentsAndTeachers < ActiveRecord :: Migration [5.1]2 def change3 create_table :students do |t|4 t.string :firstName5 t.string :lastName6 end78 create_table :teachers do |t|9 t.string :name
10 end1112 create_table :students_teachers , id: false do |t| #id:
false - tabela nie będzie zawierała klucza głównego13 t.belongs_to :student14 t.belongs_to :teacher15 end16 end17 end
Migracja
students
Model: Studenthas and belongs to many :teachers
id: integer
firstName: string
lastName: string
students teachers
student id: integer
teacher id: integer
teachers
Model: Teacherhas and belongs to many :students
id: integer
name: string
Dr inż. Stanisław Polak 181
Framework Ruby on Rails Model Asocjacje
Asocjacja polimorficzna
1 class Picture < ApplicationRecord2 belongs_to :imageable , polymorphic: true3 end45 class Student < ApplicationRecord6 has_many :pictures , as: :imageable7 end89 class Teacher < ApplicationRecord
10 has_many :pictures , as: :imageable11 end
Model
1 class CreatePictures < ActiveRecord :: Migration [5.1]2 def change3 create_table :pictures do |t|4 t.string :name5 t.references :imageable , polymorphic: true6 end7 end8 end
Migracja
students
Model: Studenthas many :pictures, :as => :imageable
id: integer
firstName: string
lastName: string
pictures
Model: Picturebelongs to :imageable,polymorphic: true
id: integer
name: string
imageable id: integer
imageable type: string
teachers
Model: Teacherhas many :pictures, :as => :imageable
id: integer
name: string
Dr inż. Stanisław Polak 182
Notatki
Notatki
Framework Ruby on Rails Model Przykład tworzenia aplikacji
Czynności wstępne
1 $ rails new library --skip -action -cable --skip -active -storage --skip -action -mailer2 $ cd library3 $ vi config/routes.rb4 $ bin/rake routes5 Prefix Verb URI Pattern Controller#Action6 books GET /books (.: format) books#index7 POST /books (.: format) books#create8 new_book GET /books/new(.: format) books#new9 edit_book GET /books /:id/edit (.: format) books#edit
10 book GET /books/:id(.: format) books#show11 PATCH /books /:id(.: format) books#update12 PUT /books/:id(.: format) books#update13 DELETE /books/:id(.: format) books#destroy14 subjects GET /subjects (.: format) subjects#index15 POST /subjects (.: format) subjects#create16 new_subject GET /subjects/new (.: format) subjects#new17 edit_subject GET /subjects /:id/edit (.: format) subjects#edit18 subject GET /subjects /:id(.: format) subjects#show19 PATCH /subjects /:id(.: format) subjects#update20 PUT /subjects /:id(.: format) subjects#update21 DELETE /subjects /:id(.: format) subjects#destroy
1 Rails.application.routes.draw do2 # maps HTTP verbs to controller actions automatically3 resources :books4 resources :subjects5 end
config/routes.rb
Dr inż. Stanisław Polak 184
Framework Ruby on Rails Model Przykład tworzenia aplikacji
Konfigurowanie bazy danych
1 $ vi library/config/database.yml
1 # SQLite version 3.x2 # gem install sqlite33 #4 # Ensure the SQLite 3 gem is defined in your Gemfile5 # gem ’sqlite3 ’6 #7 default: &default8 adapter: sqlite39 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
10 timeout: 50001112 development:13 <<: *default14 database: db/development.sqlite31516 # Warning: The database defined as "test" will be erased and17 # re - generated from your development database when you run "rake ".18 # Do not set this db to the same as development or production .19 test:20 <<: *default21 database: db/test.sqlite32223 production:24 <<: *default25 database: db/production.sqlite3
config/database.yml
Dr inż. Stanisław Polak 185
Notatki
Notatki
Framework Ruby on Rails Model Przykład tworzenia aplikacji
Pliki modelu
1 $ bin/rails generate model book2 invoke active_record3 create db/migrate /20140203134304 _create_books.rb4 create app/models/book.rb5 invoke test_unit6 create test/models/book_test.rb7 create test/fixtures/books.yml8 $ bin/rails generate model subject9 invoke active_record
10 create db/migrate /20140203134316 _create_subjects.rb11 create app/models/subject.rb12 invoke test_unit13 create test/models/subject_test.rb14 create test/fixtures/subjects.yml15 $ bin/rake db:create
1 class Book < ApplicationRecord2 belongs to :subject3 end
app/models/book.rb
1 class Subject < ApplicationRecord2 has many :books3 end
app/models/subject.rb
Dr inż. Stanisław Polak 186
Framework Ruby on Rails Model Przykład tworzenia aplikacji
Pliki migracji
1 class CreateBooks < ActiveRecord :: Migration [5.1]2 def change3 create_table :books do |t|4 t.belongs_to :subject #Utwórz klucz obcy5 t.string :title , :limit => 326 t.float :price7 t.text :description8 t.timestamp :created_at9 end
10 end11 end
db/migrate/* create books.rb
1 class CreateSubjects < ActiveRecord :: Migration [5.1]2 def change3 create_table :subjects do |t|4 t.string :name5 end6 end7 end
db/migrate/* create subjects.rb
1 CREATE TABLE "books" (2 "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL ,3 "subject_id" integer ,4 "title" varchar (32),5 "price" float ,6 "description" text ,7 "created_at" datetime8 );
1 CREATE TABLE "subjects" (2 "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL ,3 "name" varchar (255)4 );
1 Subject.create :name => "Physics"2 Subject.create :name => "Mathematics"3 Subject.create :name => "Chemistry"4 Subject.create :name => "Psychology"5 Subject.create :name => "Geography"
db/seeds.rb
1 $ bin/rake db:migrate2 $ bin/rake db:seed
Dr inż. Stanisław Polak 187
Notatki
Notatki
Framework Ruby on Rails Model Przykład tworzenia aplikacji
Kontroler dla książek
1 $ bin/rails generate controller books2 create app/controllers/books_controller.rb3 ...
1 class BooksController < ApplicationController2 def index3 end45 def show6 end78 def create9 end
1011 def new12 end1314 def edit15 end1617 def update18 end1920 def destroy21 end22 end
app/controllers/books controller.rb
Dr inż. Stanisław Polak 188
Framework Ruby on Rails Model Przykład tworzenia aplikacji
Wyświetlanie listy książek
1 class BooksController < ApplicationController2 def index3 @books = Book.all4 @subjects = Subject.all5 end6 ...7 end
app/controllers/books controller.rb
1 <% if @books.blank? %>2 <p>There are not any books currently in the system.</p>3 <% else %>4 <ul id="subjects">5 <% @subjects.each do |subject| %>6 <li><%= link_to subject.name , subject_path(subject) %></li>7 <% end %>8 </ul>9 <p>These are the current books in our system </p>
10 <ul id="books">11 <% @books.each do |book| %>12 <li>13 <%= link_to book.title , book_path(book) %> <!-- np. /books /3 -->14 <%= link_to ’Edit ’, edit_book_path(book) %> <!-- np. /books /3/ edit -->15 <%= link_to ’Destroy ’, book_path(book), method: :delete , data: { confirm: ’Are you sure?’ } %>16 <% end %>17 </ul>18 <% end %>19 <p><%= link_to "Add new Book", new_book_path %></p> <!-- /books/new -->
app/views/books/index.html.erb
Dr inż. Stanisław Polak 189
Mat
eriał
ydla
studen
tów
Infor
mat
yki wyd
ziału
IET
AGHw
Krako
wieNotatki
Notatki
Framework Ruby on Rails Model Przykład tworzenia aplikacji
Dodawanie nowej książki
1 class BooksController < ApplicationController2 ...3 def new4 end56 def create7 params.permit! #Wymagane w RoR 4.08 @book = Book.new(params [:book])9 if @book.save
10 redirect_to books_path # przekierowanie do akcji books#index
11 else12 render ’new’13 end14 end15 ...16 end
app/controllers/books controller.rb
1 <h1>Add new book</h1>2 <%= form_with model: Book.new , local: true do |f| %>3 <p>4 <%= f.label :title %><br>5 <%= f.text_field :title %>6 </p>7 <p>8 <%= f.label :price %><br>9 <%= f.text_field :price %>
10 </p>11 <p>12 <%= f.label :subject %><br>13 <%= collection_select (:book ,:subject_id ,Subject.all ,:id ,:
name) %>14 </p>15 <p>16 <%= f.label :description %><br>17 <%= f.text_area :description %>18 </p>19 <p>20 <%= f.submit %>21 </p>22 <% end %>23 <%= link_to ’Back ’, books_path %>
app/views/books/new.html.erb
Dr inż. Stanisław Polak 190
Framework Ruby on Rails Model Przykład tworzenia aplikacji
Wyświetlanie książki
1 class BooksController < ApplicationController2 ...3 def show4 @book = Book.find(params [:id])5 end6 ...7 end
app/controllers/books controller.rb
1 <h1><%= @book.title %></h1>2 <p><strong >Price: </strong > $<%= @book.price %><br />3 <strong >Subject: </strong > <%= link_to @book.subject.name ,
subject_path(@book.subject.id) %><br />4 <strong >Created Date:</strong > <%= @book.created_at %><br />5 </p>6 <p><%= @book.description %></p>7 <hr />8 <%= link_to ’Back ’, books_path %>
app/views/books/show.html.erb
Dr inż. Stanisław Polak 191
Notatki
Notatki
Framework Ruby on Rails Model Przykład tworzenia aplikacji
Edycja książki
1 class BooksController < ApplicationController2 ...3 def edit4 @book = Book.find(params [:id])5 @subjects = Subject.all6 end78 def update9 @book = Book.find(params [:id])
10 if @book.update(params [:book]. permit (:title , :price , :description))11 redirect_to @book12 else13 render ’edit’14 end15 end16 ...17 end
app/controllers/books controller.rb
1 <h1>Edit Book Detail </h1>2 <%= form_with model: @book , local: true do |f| %>3 <%# można i tak:4 form_with scope: :book , url: book_path(@book), local: true , method: :
patch do |f|5 local: true - nie używaj AJAX -a do wysyłania zawartości formularza6 %>78 <p>9 <%= f.label :title %><br>
10 <%= f.text_field :title %>11 </p>12 <p>13 <%= f.label :price %><br>14 <%= f.text_field :price %>15 </p>16 <p>17 <%= f.label :subject %><br>18 <%= collection_select (:book ,:subject_id ,@subjects ,:id ,:name) %>19 </p>20 <p>21 <%= f.label :description %><br>22 <%= f.text_area :description %>23 </p>24 <p>25 <%= f.submit %>26 </p>27 <% end %>28 <%= link_to ’Back ’, books_path %>
app/views/books/edit.html.erb
Dr inż. Stanisław Polak 192
Framework Ruby on Rails Model Przykład tworzenia aplikacji
Kasowanie książki
1 class BooksController < ApplicationController2 ...3 def destroy4 book = Book.find(params [:id])5 book.destroy6 redirect_to books_path7 end8 ...
app/controllers/books controller.rb
Dr inż. Stanisław Polak 193
Notatki
Notatki
Framework Ruby on Rails Model Walidacja
Wyświetlanie błędów walidacji w widoku
1 <%= form_with scope: :book , url: books_path do |f| %>2 <% if @book.errors.any? %>3 <div id="error_explanation">4 <h2 ><%= pluralize(@book.errors.count , "error") %> prohibited this book from being saved:</h2 >5 <ul>6 <% @book.errors.full_messages.each do |msg| %>7 <li ><%= msg %></li >8 <% end %>9 </ul >
10 </div >11 <% end %>12 ...13 <!-- Pola formularza -->14 <% end %>
app/views/users/new.html.erb
Dr inż. Stanisław Polak 196
Framework Ruby on Rails Model Walidacja
Pomocnicy walidacji
1 class Book < ApplicationRecord2 belongs_to :subject3 validates :title , presence:true4 validates :price , numericality: true5 end
Dr inż. Stanisław Polak 197
Notatki
Notatki
Framework Ruby on Rails Model Testy jednostkowe
Osprzęt (ang. Fixture)
I Sposób organizowania danych testowychI Podstawowe dane, którymi zapełniana jest baza danychI Jest niezależny od silnika bazy danychI Zapisujemy w formacie YAMLI Jeden model — jeden plik z osprzętem
1 #komentarz2 one:3 title: O obrocie sfer niebieskich4 description: Biały kruk5 subject: physics6 two:7 title: Lenin , działa wybrane8 price: 109 subject: physics
test/fixtures/books.yml
1 physics:2 name: Physics
test/fixtures/subjects.yml
Dr inż. Stanisław Polak 198
Framework Ruby on Rails Model Testy jednostkowe
Testy jednostkowe modeli
1 require ’test_helper ’23 class BookTest < ActiveSupport :: TestCase4 test "not_valid" do5 book = books(:one)6 assert book.valid?, "Błąd walidacji"?7 end8 #Powyższy fragment jest równoważny:9 # def test_not_valid
10 # ...11 # end1213 test "valid" do14 book = books(:two)15 assert book.valid?, "Błąd walidacji"?16 end17 end
test/models/book test.rb”
Dr inż. Stanisław Polak 199
Notatki
Notatki
Framework Ruby on Rails Model Testy jednostkowe
Przygotowywanie aplikacji do testowania i uruchamianie testów
1 $ bin/rake db:migrate2 $ bin/rake test3 Run options: --seed 1042345 # Running tests:67 F.89 Finished tests in 0.118807s, 16.8340 tests/s, 16.8340 assertions/s.
1011 1) Failure:12 BookTest# test_not_valid [/ home/polak/library/test/models/book_test .rb :7]:13 Błąd walidacji1415 2 tests , 2 assertions , 1 failures , 0 errors , 0 skips
Oznaczenia
„F” test nie został zaliczony
„.” test został zaliczony
Dr inż. Stanisław Polak 200
Framework Ruby on Rails Widok
Składniki warstwy widoku
I SzablonyI Szablony częścioweI Układy
1 <table >2 <% @books.each do |book| %>3 <tr>4 <td ><%= book.title %></td>5 <td ><%= book.price %></td>6 <td ><%= book.description %></td>7 </tr >8 <% end %>9 </table >
index.html.erb
1 json.array!( @books) do |book|2 json.extract! book , :id , :title , :price , :description3 end
index.json.jbuilder
Dr inż. Stanisław Polak 201
Mat
eriał
ydla
studen
tów
Infor
mat
yki wyd
ziału
IET
AGHw
Krako
wieNotatki
Notatki
Framework Ruby on Rails Widok
Tworzenie układu1 <!DOCTYPE html >2 <html >3 <head >4 <title >Library Info System | <%= yield(:title) %></title >5 <%= stylesheet_link_tag "application", media: "all", "data -turbolinks -track" => true %>6 <%= javascript_include_tag "application", "data -turbolinks -track" => true %>7 <%= csrf_meta_tags %>8 </head >9 <body id="library">
10 <header >11 <h1>Library Info System </h1>12 <h3>Library powered by Ruby on Rails </h3 >13 </header >14 <main >15 <%= yield %>16 </main >17 </body >18 </html >
app/views/layouts/standard.html.erb
1 <% content for(:title , ’Home’) %>2 ...
app/views/books/index.html.erb
1 class ApplicationController < ApplicationController2 layout ’standard’3 ...
app/controllers/application controller.rb
Dr inż. Stanisław Polak 202
Framework Ruby on Rails Widok
Tworzenie pomocnika
Library Info System |
1 module ApplicationHelper23 def full_title(page_title)4 base_title = "Library Info System"5 if page_title.empty?6 base_title7 else8 "#{ base_title} | #{ page_title}"9 end
10 end11 end
app/helpers/application helper.rb
1 ...2 <title ><%= full_title(yield(:title)) %></title >3 ...
app/views/layouts/standard.html.erb
Dr inż. Stanisław Polak 203
Notatki
Notatki
Framework Ruby on Rails Widok
Przesyłanie strumieniowe szablonów
1 render stream: true
Kontroler
1 <html >2 <head ><title ><%= yield :title %></title ></head >3 <body ><%= yield %></body >4 </html >
Układ
1 <% content for :title , "Main" %>2 Hello3 <% content for :title , " page" %>
Szablon
1 <html >2 <head ><title >Main page </title ></head >3 <body >Hello </body >4 </html >
Wynikowy dokument
1 <% provide :title , "Main" %>2 Hello3 <% content_for :title , " page" %>
Szablon
1 <html >2 <head ><title >Main </title ></head >3 <body >Hello </body >4 </html >
Wynikowy dokument
Dr inż. Stanisław Polak 204
Framework Ruby on Rails Widok
Plik ze stylami CSS
1 body {font -family: Helvetica , Geneva , Arial , sans -serif; font -size: small; font -color: #000; background -color: #fff; width: 760px;margin: 0 auto;}
23 a:link , a:active , a:visited {color: #CD0000; }45 input {margin -bottom: 5px; }67 p {line -height: 150%; }89 header {text -align: center;padding -bottom: 15px; }
1011 main {float: left; width: 450px; padding: 10px; }1213 main h3 {margin -top: 15px; }1415 ul#books {list -style -type: none; }1617 ul#books li {line -height: 140%; }1819 ul#subjects {width: 700px; text -align: center; padding: 5px; background -color: #ececec; border: 1px
solid #ccc; margin -bottom: 20px; }2021 ul#subjects li {display: inline; padding -left: 5px; }
app/assets/stylesheets/library.css
Dr inż. Stanisław Polak 205
Notatki
Notatki
Framework Ruby on Rails Widok
Kontroler dla przedmiotów
1 $ bin/rails generate controller subjects2 create app/controllers/subjects_controller.rb3 ...
1 class SubjectsController < ApplicationController2 def index3 end45 def show6 end78 def create9 end
10 end
app/controllers/subjects controller.rb
Dr inż. Stanisław Polak 206
Framework Ruby on Rails Widok
Wyświetlanie listy przedmiotów
1 class SubjectsController < ApplicationController2 def index3 @subjects = Subject.all4 end5 ...6 end
app/controllers/subjects controller.rb
1 <h1>Listing Subjects </h1>2 <ul id="subject_list">3 <% @subjects.each do |subject| %>4 <li><%= link_to subject.name , subject_path(subject) %> <%= "(#{ subject.books.count})" -%></li>5 <% end %>6 </ul>
app/views/subjects/index.html.erb
Dr inż. Stanisław Polak 207
Notatki
Notatki
Framework Ruby on Rails Widok
Wyświetlanie przedmiotu
1 class SubjectsController < ApplicationController2 ...3 def show4 @subject = Subject.find(params [:id])5 end6 ...7 end
app/controllers/subjects controller.rb
1 <h1><%= @subject.name -%></h1>2 <ul>3 <% @subject.books.each do |book| %>4 <li><%= link_to book.title , book_path(book) -%>5 <% end %>6 </ul>7 <%= link_to ’Back ’, subjects_path %>
app/views/subjects/show.html.erb
Dr inż. Stanisław Polak 208
Framework Ruby on Rails Widok
Dodawanie nowego przedmiotu przy użyciu AJAX-a
1 class SubjectsController < ApplicationController2 ...3 def create4 params.permit!5 @subject = Subject.new(name: params[’name’])6 if @subject.save7 render partial: ’subject ’, object: @subject8 end9 end
10 ...11 end
app/controllers/subjects controller.rb
1 <h1>Listing Subjects </h1>2 <ul id="subject_list">3 ...4 </ul>5 <%# ------------------------ %>6 <p id="add_link">7 <a href="#" data-remote="true" onclick="8 var element = document.querySelector (’#add_link ’);9 element.parentNode.removeChild(element);
10 document.querySelector (’#add_subject ’).style.display = ’block ’;
11 ">Add a Subject </a></p>12 <div id="add subject" style="display:none;">13 <%= form with model: @subject do |f| %>14 <%= f.label :name %><br>15 <%= f.text_field :name %>16 <%= submit_tag ’Add ’ %>17 <% end %>18 </div>
app/views/subjects/index.html.erb
1 <li id="subject_ <%= subject.id %>">2 <%= link_to subject.name , subject_path(subject) %>3 <%= "(#{ subject.books.count})" -%>4 </li>
app/views/subjects/ subject.html.erb
1 document.addEventListener "turbolinks:load", ->2 document.querySelectorAll("form").forEach ->3 document.body.addEventListener ’ajax:success ’, (event) ->4 element = document.createRange ().
createContextualFragment(event.detail [2]. response);
5 document.querySelector("#subject_list").appendChild(element);
6 document.body.addEventListener ’ajax:error ’, ->7 element = document.createRange ().
createContextualFragment("<p>ERROR </p>");8 document.querySelector("#subject_list").appendChild(
element);
app/assets/javascripts/subjects.coffee
Dr inż. Stanisław Polak 209
Notatki
Notatki
Framework Ruby on Rails Widok
Testy integracyjne aplikacji
1 bin/rails generate integration_test books_flows2 vim test/integration/books_flows_test.rb
1 require ’test_helper ’23 class BooksFlowsTest < ActionDispatch::IntegrationTest4 test "browse site" do5 get "/books"6 assert_response :success # Czy status odpowiedzi to 20078 get "/books/new"9 assert_response :success
1011 post "/books", params: { # Żądanie zasobu HTML12 # post "/ books.json", params: { # Żądanie zasobu JSON13 book: {14 title: "Matematyka",15 price: 116 }17 }18 # Przykładowa asercja dla JSON -a19 # json_response = JSON.parse(response.body)20 # assert_equal ’Matematyka ’,json_response [" title "]2122 assert_response :redirect23 follow redirect!24 assert_response :success2526 books = Book.all27 assert_equal 3, books.size28 book = books[books.size -1]29 assert_equal "Matematyka", book.title30 assert_equal 1, book.price31 end32 end
test/integration/books flows test.rb
Dr inż. Stanisław Polak 210
Framework Ruby on Rails Lokalizacja i umiędzynarodowienie
Umiędzynarodowienie i lokalizacja
Umiędzynarodowienie polega na dodaniu do aplikacji możliwości wpisywania, przetwarzania iwyświetlania (generowania) tekstu w różnych językach.
Lokalizacja jest procesem polegającym na dostosowaniu aplikacji do określonych ustawieńregionalnych (przetłumaczenie tekstów na odpowiedni język, dostosowanie formatuwaluty, formatu liczb, formatu dat, itp.).
Dr inż. Stanisław Polak 211
Mat
eriał
ydla
studen
tów
Infor
mat
yki wyd
ziału
IET
AGHw
Krako
wieNotatki
Notatki
Framework Ruby on Rails Lokalizacja i umiędzynarodowienie
Gem I18n
Co oferujeI Wsparcie dla języka angielskiego i języków do niego podobnychI Ułatwienie dostosowania i rozbudowywania aplikacji dla innych języków
Ogólna struktura gem-aI Publiczne API frameworku I18n — moduł Ruby z publicznymi metodami i definicjami,
określającymi sposób działania bibliotekiI Domyślny back-end (celowo nazywany prostym back-endem) , implementujący powyższe metody
Dr inż. Stanisław Polak 212
Framework Ruby on Rails Lokalizacja i umiędzynarodowienie
Konfiguracja modułu I18n
1 en:2 title: "Library Info System"3 info: "Library powered by Ruby on Rails %{ version
}"
config/locales/en.yml
1 pl:2 title: "Biblioteczny System Informacyjny"3 info: "Biblioteka w oparciu o Ruby on Rails %{
version}"
config/locales/pl.yml
1 ...2 # The default locale is :en and all translations from config/locales /*.rb ,yml are auto loaded.3 # config.i18n.load_path += Dir[Rails.root.join(’my ’, ’locales ’, ’*.{rb ,yml}’).to_s]4 # config.i18n. default_locale = :de5 ...
config/application.rb
1 $ vi Gemfile2 $ bundle install
Instalowanie gem-a ’rails-18n’
1 ...2 gem ’rails -i18n’
Gemfile
Dr inż. Stanisław Polak 213
Notatki
Notatki
Framework Ruby on Rails Lokalizacja i umiędzynarodowienie
Wyświetlanie tekstu wielojęzycznego
1 ...2 <header >3 <h1 ><%= t(’title’) %></h1>4 <h3 ><%= t(’info’,version: Rails.version) %></h3>5 <p><%= l Time.now %></p>6 </header >7 ...
app/views/layouts/standard.html.erb
1 <% if @books.blank? %>2 <p>Obecnie w systemie nie ma żadnych książek </p>3 <% else %>4 <ul id="subjects">5 <% @subjects.each do |subject| %>6 <li ><%= link_to subject.name , subject_path(subject) %></li>7 <% end %>8 </ul >9 <p>Oto książki znajdujące się w naszym systemie </p>
10 <ul id="books">11 <% @books.each do |book| %>12 <li>13 <%= link_to book.title , book_path(book) %>14 <%= link_to ’Edytuj ’, edit_book_path(book) %>15 <%= link_to ’Usuń’, book_path(book), method: :delete , data: { confirm: ’Jesteś pewien?’ } %>16 <% end %>17 </ul >18 <% end %>19 <p><%= link_to "Dodaj nową książkę", new_book_path -%></p>
app/views/books/index.pl.html.erb
Dr inż. Stanisław Polak 214
Framework Ruby on Rails Lokalizacja i umiędzynarodowienie
„Leniwe” wyszukiwanie
1 pl:2 layouts:3 standard:4 title: "Biblioteczny System Informacyjny"5 info: "Biblioteka w oparciu o Ruby on Rails %{ version}"
config/locales/pl.yml
1 ...2 <header >3 <h1 ><%= t(’.title’) %></h1>4 <h3 ><%= t(’.info’,version: Rails.version) %></h3>5 </header >6 ...
app/views/layouts/standard.html.erb
Dr inż. Stanisław Polak 215
Notatki
Notatki
Framework Ruby on Rails Lokalizacja i umiędzynarodowienie
Określanie języka ustawień regionalnych
I Na podstawie parametrów URLI Na podstawie nazwy domenyI Na podstawie informacji
dostarczonych przez klientaI Nagłówek „Accept-Language”I Baza GeoIP lub podobneI Profil użytkownika
1 #Przykładowy URL: http :// localhost :3000/ books?locale=pl2 class ApplicationController < ActionController ::Base3 before_action :set_locale45 def set_locale6 I18n.locale = params [: locale] || I18n.default_locale7 end8 end
app/controllers/application controller.rb
Dr inż. Stanisław Polak 216
Framework Ruby on Rails Lokalizacja i umiędzynarodowienie
Tłumaczenie rekordów bazy danych
1 $vi Gemfile2 $ bundle install3 $ vi app/models/book.rb4 $ bin/rails generate migration AddTranslationToBooks5 $ vi db/migrate /* _add_translation_to_books.rb6 $ bin/rake db:migrate7 $ vi app/controllers/books_controller.rb
1 source ’https :// rubygems.org’2 gem ’globalize ’
Gemfile
Dr inż. Stanisław Polak 217
Notatki
Notatki
Framework Ruby on Rails Uwierzytelnianie i autoryzacja Gem „Device”
Gem „Devise”Ogólna charakterystyka
I Oparty na Rack-uI Kompletne rozwiązanie MVC oparte na silnikach RailsI Jest oparty na koncepcji modułowej: „Używasz tylko tego, czego naprawdę potrzebujesz”
Moduły
1. Database Authenticatable
2. Omniauthable
3. Confirmable
4. Recoverable
5. Registerable
6. Rememberable
7. Trackable
8. Timeoutable
9. Validatable
10. Lockable
Dr inż. Stanisław Polak 218
Framework Ruby on Rails Uwierzytelnianie i autoryzacja Gem „Device”
Instalowanie gema
1 $ vi Gemfile2 $ bundle install
1 ...2 gem ’devise ’3 gem ’devise -i18n’
Gemfile
Dr inż. Stanisław Polak 219
Notatki
Notatki
Framework Ruby on Rails Uwierzytelnianie i autoryzacja Gem „Device”
Inicjalizacja
1 $ bin/rails generate devise:install2 create config/initializers/devise.rb3 create config/locales/devise.en.yml4 =========================================56 Some setup you must do manually if you haven ’t yet:7 ...89 $ vi config/initializers/devise.rb
1 # Use this hook to configure devise mailer , warden hooks andso forth.
2 # Many of these configuration options can be set straight inyour model.
3 Devise.setup do |config|4 # The secret key used by Devise. Devise uses this key to
generate5 # random tokens. Changing this key will render invalid all
existing6 # confirmation , reset password and unlock tokens in the
database.7 config.secret_key = ’6
b255d21928f0ba7669192e8d286c139cc4b2dea ’89 # ==> Mailer Configuration
10 # Configure the e-mail address which will be shown in Devise:: Mailer ,
11 # note that it will be overwritten if you use your ownmailer class
12 # with default "from" parameter.13 config.mailer_sender = ’please -change -me -at-config -
initializers [email protected]’1415 # Configure the class responsible to send e-mails.16 # config.mailer = ’Devise :: Mailer ’17 ...
config/initializers/devise.rb
Dr inż. Stanisław Polak 220
Framework Ruby on Rails Uwierzytelnianie i autoryzacja Gem „Device”
Konfigurowanie
1 config.action_mailer.default_url_options = { :host => ’localhost :3000’ }
config/environments/development.rb
1 <main >2 <p class="notice" ><%= notice %></p>3 <p class="alert" ><%= alert %></p>4 <%= yield %>5 </main >
app/views/layouts/standard.html.erb
1 ...2 root :to => "books#index"
config/routes.rb”
Dr inż. Stanisław Polak 221
Mat
eriał
ydla
studen
tów
Infor
mat
yki wyd
ziału
IET
AGHw
Krako
wieNotatki
Notatki
Framework Ruby on Rails Uwierzytelnianie i autoryzacja Gem „Device”
Dodawanie „Devise” do modelu
1 $ bin/rails generate devise user2 invoke active_record3 create db/migrate /20140219113545 _devise_create_users.rb4 create app/models/user.rb5 invoke test_unit6 create test/models/user_test.rb7 create test/fixtures/users.yml8 insert app/models/user.rb9 route devise_for :users
1011 $ bin/rake db:migrate12 == DeviseCreateUsers: migrating ==============================================13 -- create_table (:users)14 -> 0.0404s15 -- add_index (:users , :email , {: unique=>true})16 -> 0.0014s17 -- add_index (:users , :reset_password_token , {: unique=>true})18 -> 0.0013s19 == DeviseCreateUsers: migrated (0.0439s) =====================================
Dr inż. Stanisław Polak 222
Framework Ruby on Rails Uwierzytelnianie i autoryzacja Gem „Device”
Dodawanie atrybutu „admin”
1 $ bin/rails generate migration AddAdminToUsersadmin:boolean
2 invoke active_record3 create db/migrate /20140221085221
_add_admin_to_users.rb45 $ vi db/migrate /* _add_admin_to_users.rb67 $ bin/rake db:migrate8 == AddAdminToUsers: migrating ==9 -- add_column (:users , :admin , :boolean , {: default=>
false})10 -> 0.0213s11 == AddAdminToUsers: migrated (0.0215s) ==
1 class AddAdminToUsers < ActiveRecord :: Migration2 def change3 add_column :users , :admin , :boolean , default:
false4 end5 end
db/migrate/* add admin to users.rb
Dr inż. Stanisław Polak 223
Notatki
Notatki
Framework Ruby on Rails Uwierzytelnianie i autoryzacja Gem „Device”
Wymuszanie uwierzytelniania
1 class ApplicationController < ActionController ::Base2 protect_from_forgery with: :exception3 before_action :set_locale ,:authenticate user! #Tekst występujący po znaku ’_’ jest nazwą modelu4 ...5 end
app/controllers/application controller.rb
Dr inż. Stanisław Polak 224
Framework Ruby on Rails Uwierzytelnianie i autoryzacja Gem „Device”
Wyświetlanie informacji o zalogowanym użytkowniku
1 ...2 <aside >3 <% if user_signed_in? %>4 <%=t(’.logged_html ’,email: current_user.email) %>5 <br>6 <%= link_to t(’.edit_profile ’), edit_user_registration_path %> |7 <%= link_to t(’.logout ’), destroy_user_session_path , method: :delete %>8 <% else %>9 <%= link_to t(’.sign_up ’), new_user_registration_path %> |
10 <%= link_to t(’.login ’), new_user_session_path %>11 <% end %>12 </aside >13 </body >14 </html >
app/views/layouts/standard.html.erb
1 en:2 layouts:3 standard:4 ...5 logged_html: "Logged in as <strong >%{ email}</strong >"6 edit_profile: "Edit profile"7 logout: "Logout"8 sign_up: "Sign up"9 login: "Login"
config/locales/en.yml
1 en:2 layouts:3 standard:4 ...5 logged_html: "Zalogowany jako <strong >%{ email}</strong >"6 edit_profile: "Edytuj profil"7 logout: "Wyloguj"8 sign_up: "Zarejestruj się"9 login: "Zaloguj"
config/locales/pl.yml
Dr inż. Stanisław Polak 225
Notatki
Notatki
Framework Ruby on Rails Uwierzytelnianie i autoryzacja Gem „Device”
Rejestracja i logowanie
Dr inż. Stanisław Polak 226
Framework Ruby on Rails Gem „Pundit”
Gem „Pundit”Ogólna charakterystyka
I Umożliwia stworzenie prostego, solidnego i skalowalnego systemu autoryzacjiI Autoryzacja w oparciu o klasy politykI Pozwala określić zakres widoczności rekordów BD dla użytkownikówI Wspomaga obsługę „silnych” parametrów
Dr inż. Stanisław Polak 227
Notatki
Notatki
Framework Ruby on Rails Gem „Pundit”
Instalowanie gema
1 $ vi Gemfile2 $ bundle install
1 ...2 gem ’pundit ’
Gemfile
Dr inż. Stanisław Polak 228
Framework Ruby on Rails Gem „Pundit”
Dodawanie „Pundit” do kontrolera
1 class ApplicationController < ActionController ::Base2 include Pundit3 ...4 end
app/controllers/application controller.rb
Dr inż. Stanisław Polak 229
Notatki
Notatki
Framework Ruby on Rails Gem „Pundit”
Przykładowa polityka dostępu
Zwykły użytkownikI Może wyświetlać listę książekI Może wyświetlać informacje o pojedynczej
książceI Może usuwać książki z Chemii
AdministratorI Może wyświetlać listę książekI Może wyświetlać informacje o pojedynczej
książceI Może dodawać nowe książkiI Może usuwać książkiI Może edytować książki
Dr inż. Stanisław Polak 230
Framework Ruby on Rails Gem „Pundit”
Tworzenie pliku z polityką dostępu
1 $ bin/rails generate pundit:install2 create app/policies/application_policy.rb3 $ cat app/policies/application_policy.rb4 $ vi app/policies/book_policy.rb
1 class BookPolicy < ApplicationPolicy2 def create?3 user.admin?4 end56 def update?7 user.admin?8 end9
10 def destroy?11 user.admin? or record.subject.name == "Chemistry"12 end13 end
app/policies/book policy.rb
Dr inż. Stanisław Polak 231
Mat
eriał
ydla
studen
tów
Infor
mat
yki wyd
ziału
IET
AGHw
Krako
wieNotatki
Notatki
Framework Ruby on Rails Gem „Pundit”
Sprawdzanie uprawnień w obrębie widoku
1 ...2 <ul id="books">3 <% @books.each do |book| %>4 <li>5 <%= link_to book.title , book_path(book) %>6 <% if policy(book).edit? %>7 <%= link_to ’Edytuj ’, edit_book_path(book) %>8 <% end %>9 <% if policy(book).destroy? %>
10 <%= link_to ’Usuń’, book_path(book), method: :delete , data: { confirm: ’Jesteś pewien?’ } %>11 <% end %>12 <% end %>13 </ul >14 ...15 <p>16 <% if policy(Book.new).create? %>17 <%= link_to "Dodaj nową książkę", new_book_path -%>18 <% end %>19 </p>
app/views/books/index.pl.html.erb
Dr inż. Stanisław Polak 232
Framework Ruby on Rails Gem „Pundit”
Użycie autoryzacji w kontrolerze
1 class BooksController < ApplicationController2 after_action :verify authorized, :except => :index3 ...4 #http :// localhost :3000/ books/new5 def new6 @book = Book.new7 #Przerwij proces wykonywania akcji , jeżeli użytkownik nie ma stosownych uprawnień8 authorize @book #raise "not authorized " unless BookPolicy .new(current_user , @book).new?9 end
10 ...11 end
app/controllers/books controller.rb
Dr inż. Stanisław Polak 233
Notatki
Notatki
Framework Ruby on Rails Źródła
Źródła I
I Jamis Buck. Method visibility in Ruby. url:http://weblog.jamisbuck.org/2007/2/23/method-visibility-in-ruby.
I Radosław Bułat. Blog. url: http://radarek.jogger.pl/.
I RoR community. Ruby on Rails guides. url: http://guides.rubyonrails.org/.
I Michael Hartl. Ruby on Rails Tutorial. url: https://www.railstutorial.org/book.
I Blake Mizerany. Sinatra - documentation. url:http://www.sinatrarb.com/documentation.html.
I Michael Morin. Using Rack. url: http://ruby.about.com/od/rack/a/Using-Rack.htm.
I Aleksander Pohl. Ruby intro. url: http://www.apohllo.pl/dydaktyka/ruby/intro/.
I Arnau Sanches. Functional Programming with Ruby. url:http://www.slideshare.net/tokland/functional-programming-with-ruby-9975242.
I Sergio Tapia. How to use Rails 4.1 ActionPack Variants. url:http://tech.pro/tutorial/2049/how-to-use-rails-41-actionpack-variants.
I Techotopia.com. Ruby Essentials. url:http://www.techotopia.com/index.php/Ruby_Essentials.
I tutorialspoint.com. Ruby on Rails Tutorial. url:http://www.tutorialspoint.com/ruby-on-rails/.
Dr inż. Stanisław Polak 234
Framework Ruby on Rails Źródła
Źródła II
I Wikipedia. Kurs PHP. url: http://pl.wikibooks.org/wiki/PHP.
I Wikipedia. Kurs Ruby. url: http://pl.wikibooks.org/wiki/Ruby.
I Wikipedia. url: http://pl.wikipedia.org/.
Dr inż. Stanisław Polak 235
Notatki
Notatki