Más contenido relacionado La actualidad más candente (19) Similar a Ruby Grundlagen (16) Ruby Grundlagen1. Ruby
Workshop
–
Skriptum
Julian
Fischer,
Clemens
Kofler
München,
19.-‐21.
Dezember
2011
©
2011,
Julian
Fischer
und
Clemens
Kofler
2. Installation
.........................................................................................................................
7
Vorbereitung
des
Systems
...............................................................................................................................................
7
Installation
von
Ruby
mittels
RVM
..............................................................................................................................
7
Installation
von
RVM
..........................................................................................................................................................
7
Installation
von
Ruby
.........................................................................................................................................................
8
Auswahl
der
Ruby-‐Version
...............................................................................................................................................
8
Update
von
RVM
...................................................................................................................................................................
8
Literaturempfehlungen
....................................................................................................................................................
9
Gratis
.........................................................................................................................................................................................
9
Editoren
...................................................................................................................................................................................
9
Editoren
....................................................................................................................................................................................
9
IDEs
............................................................................................................................................................................................
9
Git
Crashkurs
....................................................................................................................
10
Standard
Workflow
.........................................................................................................................................................
10
Klonen
des
Repositories
..................................................................................................................................................
10
Updaten
des
Repositories
..............................................................................................................................................
10
Hinzufügen
und
Löschen
von
Dateien
......................................................................................................................
10
...................................................................................................................................................................................
11
Commit
Einspielen
der
Änderungen
...........................................................................................................................................
11
Branching
.............................................................................................................................................................................
11
Literaturempfehlungen
.................................................................................................................................................
11
Gratis
......................................................................................................................................................................................
11
Ruby
Basics
......................................................................................................................
12
Variablen
..............................................................................................................................................................................
12
Typisierung
..........................................................................................................................................................................
12
Variablentypen
und
–namen
........................................................................................................................................
12
Mathematische
Funktionen
.........................................................................................................................................
13
Standardoperationen
......................................................................................................................................................
13
Weitere
Funktionen
.........................................................................................................................................................
13
Strings
(Zeichenketten)
.................................................................................................................................................
14
Deklaration
..........................................................................................................................................................................
14
Informationen
über
einen
String
...............................................................................................................................
14
Veränderung
eines
Strings
............................................................................................................................................
15
Type
Casting
........................................................................................................................................................................
15
Methoden
.............................................................................................................................................................................
15
Deklaration
und
Verwendung
.....................................................................................................................................
15
©
2011,
Julian
Fischer
und
Clemens
Kofler
3. Query-‐/Predicate-‐Methoden
........................................................................................................................................
16
Arrays
(sortierte
Listen)
...............................................................................................................................................
16
Deklaration
..........................................................................................................................................................................
16
Zugriff
auf
Elemente
........................................................................................................................................................
17
Informationen
über
Arrays
...........................................................................................................................................
17
Transformationen
.............................................................................................................................................................
17
Set-‐Operationen
.................................................................................................................................................................
18
Queue-‐/Stack-‐Operationen
...........................................................................................................................................
18
Weitere
Anwendungsfälle
.............................................................................................................................................
18
..................................................................................................................................
18
Hashes
(Schlüssel-‐Wert-‐Paare)
Deklaration
..........................................................................................................................................................................
19
Zugriff
auf
Elemente
........................................................................................................................................................
19
Informationen
über
Hashes
..........................................................................................................................................
19
Transformation
..................................................................................................................................................................
20
Symbole
................................................................................................................................................................................
20
Enumerable
.........................................................................................................................................................................
21
.............................................................................................................................................................
21
Häufige
Methoden
Minimum
und
Maximum
................................................................................................................................................
22
Informationen
über
Enumerable
...............................................................................................................................
22
Sortiertung
...........................................................................................................................................................................
22
Verwendung
von
externen
Iteratoren
......................................................................................................................
23
lambdas,
procs
und
Blöcke
...........................................................................................................................................
23
Deklaration
und
Verwendung
.....................................................................................................................................
23
Blöcke
.....................................................................................................................................................................................
24
Kontrollstrukturen
..........................................................................................................................................................
25
Boolsche
Operatoren
.......................................................................................................................................................
25
Conditionals
(if,
else
etc.)
...............................................................................................................................................
25
case/when
............................................................................................................................................................................
26
Loops
(for,
while
etc.)
......................................................................................................................................................
27
Literaturempfehlungen
.................................................................................................................................................
27
Gratis
......................................................................................................................................................................................
27
Kostenpflichtig
...................................................................................................................................................................
27
Standard-‐Library
und
Gems
..............................................................................................
29
Standard-‐Library
..............................................................................................................................................................
29
Verwendung
........................................................................................................................................................................
29
Verfügbare
Pakete
............................................................................................................................................................
29
©
2011,
Julian
Fischer
und
Clemens
Kofler
4. Status
der
Standard-‐Library
........................................................................................................................................
29
Gems
.......................................................................................................................................................................................
29
Verwendung
........................................................................................................................................................................
30
Verfügbare
Pakete
............................................................................................................................................................
30
...............................................................................................................................................
30
Auswahl
passender
Gems
Empfohlene
Gems
..............................................................................................................................................................
30
Bundler
.................................................................................................................................................................................
33
Literaturempfehlungen
.................................................................................................................................................
33
Gratis
......................................................................................................................................................................................
33
Objektorientierte
Programmierung
mit
Ruby
–
Grundlagen
.............................................
34
Klassen
und
Instanzen
...................................................................................................................................................
34
Methoden
.............................................................................................................................................................................
34
Instanzmethoden
..............................................................................................................................................................
34
Klassenmethoden
..............................................................................................................................................................
35
Hash-‐Parameter
................................................................................................................................................................
35
Multi-‐Parameter
................................................................................................................................................................
35
Variablen
..............................................................................................................................................................................
36
Instanzvariablen
...............................................................................................................................................................
36
..............................................................................................................................................................................
36
Accessors
Access
Control
(Zugriffskontrolle)
...........................................................................................................................
38
Vererbung
............................................................................................................................................................................
38
Methoden
..............................................................................................................................................................................
39
super
.......................................................................................................................................................................................
39
Literaturempfehlungen
.................................................................................................................................................
40
Gratis
......................................................................................................................................................................................
40
Objektorientierte
Programmierung
mit
Ruby
–
Fortgeschrittene
Themen
........................
41
Ruby
Objektmodell
..........................................................................................................................................................
41
Klassenhierarchien
...........................................................................................................................................................
41
Module
...................................................................................................................................................................................
41
Methoden
.............................................................................................................................................................................
43
Messages
und
Receiver
...................................................................................................................................................
43
self
............................................................................................................................................................................................
44
Duck
Typing
........................................................................................................................................................................
44
Interne
und
externe
APIs
..............................................................................................................................................
46
...................................................................................................................
46
Zugriff
auf
die
interne
API
mittels
send
Wann
sollte
man
send
nicht
verwenden?
...............................................................................................................
46
©
2011,
Julian
Fischer
und
Clemens
Kofler
5. Monkeypatching
...............................................................................................................................................................
47
ActiveSupport
.....................................................................................................................................................................
47
Metaprogramming
...........................................................................................................................................................
49
....................................................................................................................................
49
Methoden
dynamisch
erstellen
method_missing
.................................................................................................................................................................
50
Weitere
Hooks
....................................................................................................................................................................
53
Literaturempfehlungen
.................................................................................................................................................
53
Gratis
......................................................................................................................................................................................
53
Kostenpflichtig
...................................................................................................................................................................
54
Webservices
mit
Ruby
......................................................................................................
55
REST-‐Grundlagen
.............................................................................................................................................................
55
Gängige
Anwendungsfälle
.............................................................................................................................................
56
Sinatra
...................................................................................................................................................................................
56
Installation
...........................................................................................................................................................................
56
Hello
World
..........................................................................................................................................................................
56
Beispiel:
Einfacher
Kontaktmanager
.......................................................................................................................
57
Beispiel:
Einfacher
Kontaktmanager
mit
Datenbank
.......................................................................................
58
Beispiel:
Content
Type
Negotiation
...........................................................................................................................
61
Rails
........................................................................................................................................................................................
62
Konsumieren
eines
REST-‐Webservice
....................................................................................................................
64
ActiveResource
...................................................................................................................................................................
64
RestClient
..............................................................................................................................................................................
65
Literaturempfehlungen
.................................................................................................................................................
66
Gratis
......................................................................................................................................................................................
66
Kostenpflichtig
...................................................................................................................................................................
66
Integration
Testing
mit
Cucumber
und
Capybara
..............................................................
67
Integration
Testing
..........................................................................................................................................................
67
Cucumber
.............................................................................................................................................................................
67
.......................................................................................................................................................................
67
Einsatzgebiet
Installation
...........................................................................................................................................................................
68
Konfiguration
.....................................................................................................................................................................
68
Struktur
.................................................................................................................................................................................
68
Beispiel
...................................................................................................................................................................................
69
Backgrounds
.......................................................................................................................................................................
69
..........................................................................................................................................................
70
Ausführen
der
Tests
Implementierung
der
Schritte
.....................................................................................................................................
70
©
2011,
Julian
Fischer
und
Clemens
Kofler
6. Capybara
..............................................................................................................................................................................
70
.......................................................................................................................................................................
70
Einsatzgebiet
Installation
...........................................................................................................................................................................
71
Konfiguration
.....................................................................................................................................................................
71
Adapter
..................................................................................................................................................................................
71
Kommandos
.........................................................................................................................................................................
71
Literaturempfehlungen
.................................................................................................................................................
72
Gratis
......................................................................................................................................................................................
72
Kostenpflichtig
...................................................................................................................................................................
72
Deployment
mit
Capistrano
.............................................................................................
73
Grundlagen
..........................................................................................................................................................................
73
Funktionsweise
...................................................................................................................................................................
73
Voraussetzungen
...............................................................................................................................................................
73
Setup
.......................................................................................................................................................................................
73
Anatomie
eines
Capistrano-‐Setups
............................................................................................................................
74
Minimalkonfiguration
.....................................................................................................................................................
74
...........................................................................................................................................................
75
Erstes
Deployment
Vorbereitung
der
Server
................................................................................................................................................
75
Applikationsspezifisches
Setup
...................................................................................................................................
75
Deployment
..........................................................................................................................................................................
76
Weiterführende
Themen
...............................................................................................................................................
76
Definition
eigener
Tasks
................................................................................................................................................
76
Handhabung
von
sensiblen
Daten
.............................................................................................................................
77
Persistenz
über
Deployments
.......................................................................................................................................
78
Literaturempfehlungen
.................................................................................................................................................
79
Gratis
......................................................................................................................................................................................
79
Kostenpflichtig
...................................................................................................................................................................
79
©
2011,
Julian
Fischer
und
Clemens
Kofler
7. Installation
In
diesem
Kapitel
wird
das
Setup
einer
Ruby-‐Entwicklungsumgebung
unter
Linux
(z.B.
Ubuntu)
beschrieben.
Vorbereitung
des
Systems
Zunächst
müssen,
sofern
nicht
bereits
vorhanden,
einige
Bibliotheken
installiert
werden:
apt-get install build-essential openssl libreadline6
libreadline6-dev curl git-core zlib1g zlib1g-dev libssl-dev
libyaml-dev libxml2-dev libxslt-dev autoconf libc6-dev
ncurses-dev automake libtool bison subversion
Je
nachdem,
welche
Datenbanksysteme
verwendet
werden
sollen,
müssen
auch
hierfür
noch
Bibliotheken
installiert
werden:
apt-get libsqlite3-0 libsqlite3-dev sqlite3
apt-get install libmysqlclient16-dev
apt-get install libpq-dev
Installation
von
Ruby
mittels
RVM
Der
Ruby
Version
Manager
(RVM)
wird
ist
ein
beliebtes
Werkzeug,
um
verschiedene
Versionen
von
Ruby
auf
demselben
System
zu
betreiben.
Dies
ist
beispielsweise
notwendig,
wenn
in
verschiedenen
Projekten
verschiedene
Versionen
von
Ruby
im
Einsatz
sind.
Installation
von
RVM
RVM
bietet
ein
automatisches
Installationsskript,
das
via
bash
und
curl
direkt
installiert
werden
kann:
bash < <(curl -s
https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-
installer )
Außerdem
muss
RVM
in
bash_profile
geladen
werden:
echo '[[ -s "$HOME/.rvm/scripts/rvm" ]] && .
"$HOME/.rvm/scripts/rvm" # Load RVM function' >>
~/.bash_profile
source ~/.bash_profile
©
2011,
Julian
Fischer
und
Clemens
Kofler
8. Hinweis:
Bei
Verwendung
einer
anderen
Shell
muss
ggf.
eine
andere
Konfigurationsdatei
bearbeitet
werden.
Installation
von
Ruby
RVM
bietet
eine
Funktion,
die
alle
verfügbaren
Ruby-‐Versionen
anzeigt:
rvm list known
Mit
folgendem
Kommando
kann
anschließend
die
gewünschte
Version
installiert
werden
(Beispiel
1.9.3-‐p0):
rvm install 1.9.3-p0
Auswahl
der
Ruby-‐Version
Um
eine
bestimmte
Version
von
Ruby
zu
aktivieren,
wird
rvm use
verwendet:
rvm use 1.9.3
Die
gewählte
Version
gilt
nur
in
der
aktuellen
Konsolensitzung,
d.h.
alle
weiteren
Sitzungen
behalten
die
vom
System
definierte
Standardversion
von
Ruby.
Um
eine
andere
Version
als
Standards
zu
setzen,
kann
rvm use
mit
dem
Flag
--default
aufgerufen
werden:
rvm use 1.9.3 --default
Projektspezifische
Konfiguration
RVM
unterstützt
projektspezifische
Konfigurationen.
Dazu
muss
eine
Datei
namens
.rvmrc
im
Verzeichnis
des
jeweiligen
Projekts
angelegt
werden.
Beim
Wechsel
in
dieses
Verzeichnis
führt
RVM
automatisch
diese
Datei
aus.
So
kann
z.B.
die
Ruby-‐Version
jedes
einzelnen
Projekts
in
der
jeweiligen
.rvmrc
Datei
definiert
werden.
rvm use 1.9.3
Update
von
RVM
RVM
sollte
häufig
geupdatet
werden,
um
stets
Zugriff
auf
die
neuesten
Releases
der
einzelnen
Ruby-‐Versionen
zu
haben.
rvm get head
rvm get stable
rvm get 1.9.2
©
2011,
Julian
Fischer
und
Clemens
Kofler
9. Literaturempfehlungen
Gratis
https://rvm.beginrescueend.com/
http://screencasts.org/episodes/how-‐to-‐use-‐rvm
http://ryanbigg.com/2010/12/ubuntu-‐ruby-‐rvm-‐rails-‐and-‐you/
Editoren
Die
meisten
gängigen
Editoren
unterstützen
Ruby
ab
Werk
oder
bieten
Erweiterungen
für
Ruby
an.
Hier
bieten
wir
eine
unvollständige
Liste
von
Editoren,
die
wir
bereits
im
Einsatz
mit
Ruby
gesehen
haben.
Editoren
TextMate:
http://macromates.com/
(Mac
OS
X)
vim:
http://www.vim.org/
emacs:
http://www.gnu.org/s/emacs/
redcar:
http://redcareditor.com/
jEdit:
http://jedit.org/
gedit
(gmate:
https://github.com/gmate/gmate)
e
Text
Editor:
http://e-‐texteditor.com/
IDEs
RubyMine:
http://www.jetbrains.com/ruby/
RadRails:
http://aptana.com/products/radrails
Aptana
Studio:
http://aptana.com/products/studio3
NetBeans:
http://netbeans.org/
(Ruby
Plugin:
http://plugins.netbeans.org/plugin/38549/ruby-‐and-‐rails)
©
2011,
Julian
Fischer
und
Clemens
Kofler
10. Git
Crashkurs
Git
ist
ein
mächtiges
Versionskontrollsystem.
In
diesem
Abschnitt
soll
eine
kurze
Übersicht
über
den
wichtigsten
Workflow
gegeben
werden.
Details
und
tiefer
gehende
Themen
können
im
gratis
eBook
“Pro
Git”
nachgelesen
werden.
Standard
Workflow
Klonen
des
Repositories
Das
erste
Auschecken
des
Repositories
erfolgt
mittels
git clone:
git clone git://url/path
Dabei
werden
sämtliche
Daten
des
Repositories
(inkl.
Branches
und
Tags)
auf
die
locale
Maschine
kopiert.
Updaten
des
Repositories
Um
die
neuesten
Updates
aus
dem
Repository
zu
erhalten,
wird
git pull
verwendet:
git pull
Dabei
werden
etwaige
Änderungen
mit
lokalen
Änderungen
zusammengeführt
(merge),
wobei
es
zu
Konflikten
kommen
kann.
Häufig
können
Konflikte
vermieden
werden,
indem
git pull
mit
dem
Flag
--rebase
verwendet
wird:
git pull --rebase
Hier
nimmt
Git
zunächst
alle
lokalen
Änderungen
seit
dem
letzten
Update
zurück,
spielt
das
Update
vom
Server
ein
(fast
forward)
und
fügt
anschließend
die
lokalen
Änderungen
wieder
einzeln
hinzu.
Wenn
eine
der
lokalen
Änderungen
einen
Konflikt
auslöst,
kann
dieser
behoben
werden,
was
üblicherweise
einfacher
ist,
als
alle
Konflikte
auf
einmal
zu
beheben.
Hinzufügen
und
Löschen
von
Dateien
Um
Dateien
für
den
nächsten
Commit
hinzuzufügen,
wird
git add
verwendet:
git add README
git
rm
wird
zum
Löschen
verwendet:
git rm README
©
2011,
Julian
Fischer
und
Clemens
Kofler
11. Commit
Im
Gegensatz
zu
anderen
Versionskontrollsystemen
wie
z.B.
Subversion
erfolgt
ein
Commit
in
Git
lokal,
d.h.
die
Änderungen
werden
nicht
sofort
am
Server
abgelegt.
Das
notwendige
Kommando
heißt
git commit
und
wird
üblicherweise
zusammen
mit
dem
Modifikator
-m
(Message)
verwendet:
git commit -m 'I made a change'
Einspielen
der
Änderungen
Um
die
Änderungen
auf
dem
Server
einzuspielen,
wird
git push
verwendet:
git push
Dieses
Kommando
funktioniert
nur,
wenn
lokal
die
aktuellste
Version
des
Servers
vorhanden
ist
–
man
sagt,
der
Branch
ist
“fast
forwardable”.
Branching
Das
Branching-‐Modell
von
Git
ist
wohl
am
leichtesten
anhand
des
Git
Flow
Workflow
zu
verstehen.
Details
und
Illustrationen
finden
sich
im
entsprechenden
Blogpost:
http://nvie.com/posts/a-‐successful-‐git-‐branching-‐model/.
Literaturempfehlungen
Gratis
http://progit.org/
(Pro
Git;
auch
als
gedrucktes
Buch
erhältlich)
http://yehudakatz.com/2010/05/13/common-‐git-‐workflows/
http://nvie.com/posts/a-‐successful-‐git-‐branching-‐model/
©
2011,
Julian
Fischer
und
Clemens
Kofler
12. Ruby
Basics
Variablen
Typisierung
In
Ruby
ist,
im
Gegensatz
zu
Java
und
anderen
strenger
typisierten
Sprachen,
weder
eine
Deklaration
noch
eine
Typdefintion
notwendig.
Die
Festlegung
des
Typs
erfolgt
bei
der
Initialisierung.
a = 5 # a ist nun eine Ganzzahl mit dem Wert 5
s = “Hallo Welt” # s ist nun eine Zeichenkette
Da
kein
Typ
festgelegt
wird,
kann
sich
der
Typ
einer
Variable
bei
Bedarf
ändern.
a = 5 # a ist nun eine Ganzzahl mit dem Wert 5
a = “Hallo Welt” # a ist nun eine Zeichenkette
Variablentypen
und
–namen
Ruby
unterscheidet
verschiedene
Typen
von
Variablen:
• Lokale
Variablen:
Der
Name
beginnt
mit
einem
Kleinbuchstaben.
• Globale
Variablen:
Der
Name
beginnt
mit
$.
• Konstanten:
Der
Name
beginnt
mit
einem
Großbuchstaben.
• Instanzvariablen:
Der
Name
beginnt
mit
@.
• Klassenvariablen:
Der
Name
beginnt
mit
@@.
Abgesehen
von
den
erwähnten
Regeln
überlässt
Ruby
die
Benennung
der
Variablen
dem
Programmierer.
In
der
Ruby-‐Community
gibt
es
einige
Konventionen,
die
befolgt
werden
sollten,
um
die
Lesbarkeit
des
eigenen
Codes
für
andere
Programmierer
zu
verbessern:
• Lokale
Variablen
sowie
Instanz-‐
und
Klassenvariablen
werden
im
snake_case
geschrieben,
d.h.
einzelne
Wörter
werden
klein
geschrieben
und
durch
einen
Unterstrich
(_)
getrennt.
• Konstanten
und
globale
Variablen
werden
im
UPPER_SNAKE_CASE
geschrieben,
d.h.
einzelne
Wörter
werden
groß
geschrieben
und
durch
einen
Unterstrich
(_)
getrennt.
• Klassennamen
bilden
einen
Sonderfall:
Obwohl
sie
streng
genommen
Konstanten
sind,
werden
sie
üblicherweise
im
CamelCase
geschrieben,
d.h.
einzelne
Wörter
©
2011,
Julian
Fischer
und
Clemens
Kofler
13. werden
haben
einen
großen
Anfangsbuchstaben
und
werden
ohne
Trennzeichen
aneinander
gekettet.
• Umlaute
und
ähnliche
Sonderzeichen
sind
zwar
möglich,
sollten
aber
vermieden
werden.
• Englische
Variablennamen
werden
bevorzugt.
Mathematische
Funktionen
Rubys
mathematische
Funktionen
sind
weitgehend
ähnlich,
wie
sie
auch
in
Java,
C++
etc.
zu
finden
sind.
Standardoperationen
puts 4 + 1 # => 5
puts 4 - 1 # => 3
puts 4 * 2 # => 8
puts 4 / 2 # => 2
Wie
auch
in
anderen
Sprachen
wird
der
Typ
automatisch
auf
Fließkomma
angepasst,
wenn
ein
Operand
mit
Fließkommatyp
in
der
Berechnung
verwendet
wird:
puts 4 + 0.5 # => 4.5
puts 4 * 1.5 # => 6.0
puts 4 / 3 # => 1
puts 4 / 3.0 # => 1.33333333333333
Mathematische
Grundregeln
wie
„Punkt
vor
Strich“
werden
befolgt:
puts 4 + 2 * 3 # => 10
puts (4 + 2) * 3 # => 18
Weitere
Funktionen
Das
Math-‐Modul
bietet
komplexere
mathematische
Funktionen
wie
z.B.
trigonometrische
Funktionen
(sin,
cos
etc.),
Wurzeln
(sqrt),
Logarithmen
(log,
log2,
log10,
exp)
etc.
puts Math.sqrt(9) # => 3.0
puts Math.log10(100) # => 2.0
Außerdem
bietet
das
Math-‐Modul
die
Konstanten
PI
und
E.
©
2011,
Julian
Fischer
und
Clemens
Kofler
14. Strings
(Zeichenketten)
Deklaration
Strings
können
in
Ruby
single-‐
oder
double-‐quoted
sein.
'Hallo Welt' # => single-quoted
"Hallo Welt" # => double-quoted
Die
beiden
Varianten
unterscheiden
sich
lediglich
beim
Interpolationsverhalten:
Ein
double-‐quoted
String
kann
Variablen
interpolieren,
ein
single-‐quoted
String
jedoch
nicht:
lang = "Java"
puts "Sprache: #{lang}" # => Sprache: Java
puts 'Sprache: #{lang}' # => Sprache: #{lang}
Quotes
müssen
ggf.
escapet
werden:
puts "Ich sage: "Hallo Welt""
puts 'Ich sage: 'Hallo Welt''
Folgende
Varianten
können
verwendet
werden,
um
auf
Escaping
zu
verzichten:
puts %(Ich sage: "Hallo Welt") # dasselbe wie %Q
puts %Q(Ich sage: "Hallo Welt") # double-quoted
puts %q(Ich sage: 'Hallo Welt') # single-quoted
Weiters
kennt
Ruby
die
Heredoc-‐Notation:
poem = <<POEM
Wer reitet so spät durch Nacht und Wind?
Es ist der Vater mit seinem Kind.
POEM
puts poem
Hinweis:
Wenn
dem
Begrenzer
ein
-‐
vorangestellt
wird,
kann
der
End-‐Begrenzer
beliebig
eingerückt
werden.
Informationen
über
einen
String
lang = 'Java'
puts lang.length # => 4
puts lang.include?('e') # => false
puts lang.index('a') # => 1
©
2011,
Julian
Fischer
und
Clemens
Kofler
15. Veränderung
eines
Strings
puts lang + 'Script' # => JavaScript
puts lang.capitalize # => Java
puts lang.downcase # => java
puts lang.upcase # => JAVA
puts lang.reverse # => avaJ
puts lang.gsub('a', 'i') # => Jivi
Bei
diesen
Operationen
wird
ein
neuer
String
erzeugt
–
der
originale
String
wird
dabei
nicht
verändert.
Es
gibt
jeweils
“destruktive”
Operationen,
die
den
originalen
String
verändern:
lang << 'Script'
puts lang # => JavaScript
lang.downcase!
puts lang # => javascript
lang.reverse!
puts lang # => tpircsavaj
lang.gsub!('a', 'i')
puts lang # => tpircsivij
Type
Casting
Ein
String
kann
in
andere
Typen
umgewandelt
werden,
wenn
er
entsprechend
formatiert
ist:
puts '1.9'.to_f # => 1.9
puts '1'.to_i # => 1
puts '1.9'.to_i # => 1
Methoden
Methoden
werden
verwendet,
um
Funktionalität
zu
kapseln.
Deklaration
und
Verwendung
Im
Gegensatz
zu
Java
ist
es
in
Ruby
nicht
notwendig
(und
nicht
möglich),
Parameter
und
Rückgabewerte
zu
typisieren.
Wie
auch
bei
Variablen
werden
die
Typen
automatisch
festgelegt.
def multiply(a, b)
©
2011,
Julian
Fischer
und
Clemens
Kofler
16. a * b
end
puts multiply(4, 3) # => 12
Query-‐/Predicate-‐Methoden
Als
Query-‐
oder
Predicate-‐Methoden
werden
Methoden
bezeichnet,
die
mit
einem
Fragezeichen
(?)
enden.
Diese
Methoden
geben
per
Konvention
einen
Boolean-‐Typen
(true
oder
false)
zurück.
lang = 'Java'
puts lang.include?('a') # => true
puts lang.include?('i') # => false
Bang-‐Methoden
Als
Bang-‐Methoden
werden
Methoden
bezeichnet,
die
mit
einem
Rufzeichen
(!)
enden.
Die
Bang-‐Methode
zeigt
üblicherweise
an,
dass
die
“normale”
Methode
(=
ohne
!)
mit
zusätzlichen
Effekten
ausgeführt
wird.
lang = 'Java'
lang.upcase # verändert das Original nicht
puts lang # => Java
lang.upcase! # verändert das Original
puts lang # => JAVA
# in ActiveRecord wird versucht, eine Person anzulegen
Person.create # => im Fehlerfall wird false zurückgegeben
Person.create! # => im Fehlerfall wird eine Exception geworfen
Arrays
(sortierte
Listen)
Ararys
sind
sortierte
Listen
von
Elementen.
Deklaration
Arrays
werden
mit
einer
Literal-‐Syntax
deklariert.
Die
Größe
des
Arrays
wird
automatisch
bestimmt
und
erweitert
und
muss
daher
nicht
explizit
angegeben
werden.
numbers = [1, 3, 3, 7]
p numbers # => [1, 3, 3, 7]
languages = ['Java', 'Ruby']
©
2011,
Julian
Fischer
und
Clemens
Kofler
17. p languages # => ["Java", "Ruby"]
Aufgrund
der
dynamischen
Typisierung
kann
ein
Array
in
Ruby
Elemente
beliebiger
verschiedener
Typen
enthalten
(vgl.
untypisierte
ArrayList
in
Java).
mixed = [1, 'Java', 2, 'Ruby']
p mixed # => [1, "Java", 2, "Ruby"]
String
Arrays
können
mit
einer
alternativen
Literal-‐Syntax
deklariert
werden:
languages = %w(Java Ruby)
p languages # => ["Java", "Ruby"]
script = 'Script'
languages = %W(Java#{script} Ruby)
p languages # => ["JavaScript", "Ruby"]
Zugriff
auf
Elemente
Arrays
sind
mit
Ganzzahlen
indexiert.
Die
Indexierung
beginnt
wie
in
vielen
anderen
Sprachen
mit
0.
Der
Zugriff
auf
ein
nicht
existierendes
Element
gibt
nil
zurück.
Ein
negativer
Index
beginnt
vom
Ende
des
Arrays.
languages = ['Java', 'Ruby']
p languages[1] # => "Ruby"
p languages[2] # => nil
p languages[-1] # => "Ruby"
Das
Schreiben
von
Werten
funktioniert
ähnlich:
languages[0] = 'JavaScript'
p languages # => ["JavaScript", "Ruby"]
languages[2] = 'C#'
p languages # => ["JavaScript", "Ruby", "C#"]
Informationen
über
Arrays
languages = ['Java', 'Ruby', 'C#']
puts languages.length # => 3
puts languages.empty? # => false
puts languages.index('C#') # => 1
Transformationen
p [['Java', 'C#'], ['Ruby', 'JavaScript']].flatten
# => ["Java", "C#", "Ruby", "JavaScript"]
©
2011,
Julian
Fischer
und
Clemens
Kofler
18. puts ['Java', 'C#', 'Ruby', 'JavaScript'].join(', ')
# => Java, C#, Ruby, JavaScript
p ["Java", "Ruby", "Java"].uniq # => ["Java", "Ruby"]
Set-‐Operationen
Arrays
in
Ruby
unterstützen
gängige
Set-‐Operationen
wie
Schnitt
(intersect),
Vereinigung
(union),
Ausschuss
(diff)
und
Addition.
p ["Java", "Ruby"] & ["Ruby", "JavaScript"]
# => ["Ruby"]
p ["Java", "Ruby"] | ["Ruby", "JavaScript"]
# => ["Java", "Ruby", "JavaScript"]
p ["Java", "Ruby"] + ["Ruby", "JavaScript"]
# => ["Java", "Ruby", "Ruby", "JavaScript"]
p ["Java", "Ruby"] - ["Java", "JavaScript"]
# => ["Ruby"]
Queue-‐/Stack-‐Operationen
Arrays
können
wie
Queues/Stacks
verwendet
werden.
languages = ['Ruby']
languages.unshift('Java')
p languages # => ["Java", "Ruby"]
languages.push('C#')
p languages # => ["Java", "Ruby", "C#"]
puts languages.shift # => Java
p languages # => ["Ruby", "C#"]
puts languages.pop # => C#
p languages # => ["Ruby"]
Weitere
Anwendungsfälle
Für
weitere
Anwendungsfälle
bietet
die
Ruby
Standard
Library
die
Klassen
Set
und
SortedSet,
die
jeweils
Duplikate
verhindert.
Hashes
(Schlüssel-‐Wert-‐Paare)
Hashes
sind
Schlüssel-‐Wert-‐Paare.
Sie
werden
besonders
gern
für
Parameterlisten
verwendet,
wo
die
Reihenfolge
der
Parameter
keine
Rolle
spielt.
©
2011,
Julian
Fischer
und
Clemens
Kofler
19. Deklaration
Hashes
werden
mit
einer
Literal-‐Syntax
deklariert.
hash = { 'a' => 100, 'b' => 50, 'c' => 10 }
p hash # => {"a"=>100, "b"=>50, "c"=>10}
Aufgrund
der
dynamischen
Typisierung
kann
ein
Array
in
Ruby
Elemente
beliebiger
verschiedener
Typen
enthalten.
hash = { 'a' => 100, 'b' => 'Hallo Welt' }
p hash # => {"a"=>100, "b"=>"Hallo Welt"}
Obwohl
theoretisch
jedes
Objekt
als
Key
verwendet
werden
kann,
werden
in
der
Regel
Strings
oder
Symbole
(mehr
dazu
später)
verwendet.
Hashes
können
auch
direkt
aus
Name-‐Wert-‐Paaren
erzeugt
werden:
p Hash['a', 100, 'b', 50] # => {"a"=>100, "b"=>50}
p Hash[[['a', 100], ['b', 50]]] # => {"a"=>100, "b"=>50}
Zugriff
auf
Elemente
Der
Zugriff
auf
Hash-‐Elemente
erfolgt
auf
dieselbe
Art
wie
bei
Arrays:
hash = { 'a' => 100, 'b' => 50, 'c' => 10 }
puts hash['a'] # => 100
Es
können
auch
mehrere
Werte
auf
einmal
ausgelesen
werden:
p hash.values_at('c', 'a') # => [10, 200]
Ein
Ausschnitt
eines
Hashes
kann
wie
folgt
erzeugt
werden:
p hash.slice ('a', 'c') # => {"a"=>100, "c"=>10}
Wie
bei
Arrays
erzeugt
ein
Zugriff
auf
ein
nicht
existierendes
Element
keinen
Fehler,
sondern
gibt
nil
zurück.
puts hash['d'] # => nil
Das
Setzen
eines
Wertes
erfolgt
ebenfalls
auf
dieselbe
Art
wie
bei
Arrays:
hash['a'] = 200
puts hash['a'] # => 200
Informationen
über
Hashes
p hash.keys # => ["a", "b", "c"]
puts hash.size # => 3
©
2011,
Julian
Fischer
und
Clemens
Kofler
20. puts hash.empty? # => false
puts hash.has_key?('b') # => true
puts hash.has_value?(500) # => false
Transformation
p hash.invert # => {50=>"b", 200=>"a", 10=>"c"}
p hash.to_a # => [["a", 200], ["b", 50], ["c", 10]]
puts hash.delete('a') # => 200
p hash # => {"b"=>50, "c"=>10}
p hash.merge('a' => 50) # => {"a"=>50, "b"=>50, "c"=>10}
p hash # => {"b"=>50, "c"=>10}
Hinweis:
merge
verändert
den
originalen
Hash
nicht.
Um
den
originalen
Hash
direkt
zu
verändern,
kann
die
Bang-‐Variante
(merge!)
verwendet
werden.
Symbole
Symbole
sind
benannte
Literale,
die
an
einer
speziellen
Stelle
im
Speicher,
der
so
genannten
symbol
table,
abgelegt
sind.
Sie
sind
durch
einen
führenden
Doppelpunkt
(:)
gekennzeichnet.
Im
Gegensatz
zu
Strings
behält
ein
Symbol
stets
seine
Speicheradresse
und
ist
daher
immer
“identisch”.
puts 'Test'.object_id # => 2152459300
puts 'Test'.object_id # => 2152449720
puts :test.object_id # => 144328
puts :test.object_id # => 144328
Verwendung
von
Symbolen
Symbole
werden
hauptsächlich
als
Keys
für
Hashes
verwendet:
hash = { :a => 1, :b => 2 }
puts hash[:a] # => 1
Außerdem
dienen
sie
häufig
als
Ersatz
für
(Integer-‐)Konstanten.
NORTH = 1
EAST = 2
SOUTH = 3
©
2011,
Julian
Fischer
und
Clemens
Kofler
21. WEST = 4
def move(direction)
if direction == NORTH
moveNorth
# ...
end
end
move(NORTH)
Dieser
Code
wird
in
Ruby
tendenziell
so
geschrieben:
def move(direction)
if direction == :north
moveNorth
# ...
end
end
move(:north)
Enumerable
Enumerable
ist
ein
Modul
bzw.
Mixin
(vgl.
Interface
in
Java),
das
verschiedene
Iterator-‐Methoden
zur
Verfügung
stellt.
Jede
Klasse,
die
“enumerable”
sein
will,
muss
eine
Methode
Names
each
bereitstellen.
Die
Klassen
Array
und
Hash
verwenden
Enumerable:
numbers = [50, 40, 30, 20, 10]
numbers.each { |n| puts n }
hash = { 'a' => 100, 'b' => 50, 'c' => 10 }
hash.each { |key, value| puts "#{key}: #{value}" }
numbers.each_with_index { |n, i| puts "#{i}: #{n}" }
Häufige
Methoden
• map
(Alias:
collect):
wendet
den
übergebenen
Block
auf
jedes
Element
an
• select
(Alias:
find_all):
selektiert
alle
Elemente,
für
die
der
übergebene
Block
true
zurück
gibt
©
2011,
Julian
Fischer
und
Clemens
Kofler
22. • reject:
selektiert
alle
Elemente,
für
die
der
übergebene
Block
false
zurück
gibt
• detect
(Alias:
find):
gibt
das
erste
Element
zurück,
für
das
der
übergebene
Block
true
zurück
gibt
(nil,
wenn
keines
gefunden
wird)
p numbers.map { |n| n * 2 } # => [100, 80, 60, 40, 20]
p numbers.select { |n| n < 25 } # => [20, 10]
p numbers.reject { |n| n < 25 } # => [50, 40, 20]
puts numbers.detect { |n| n < 25 } # => 20
Minimum
und
Maximum
numbers = [50, 40, 30, 20, 10]
puts numbers.min # => 10
puts numbers.max # => 50
p numbers.minmax # => [10, 50]
languages = ['Java', 'Ruby', 'C#']
puts languages.max # => Ruby
puts languages.min { |l1, l2| l1.length <=> l2.length } # =>
C#
puts languages.min_by { |language| language.length } # => C#
Informationen
über
Enumerable
p numbers.any? { |n| n > 100 } # => false
p numbers.none? { |n| n > 100 } # => true
p numbers.all? { |n| n < 100 } # => true
p numbers.one? { |n| n >= 50 } # => true
Sortiertung
Auch
Sortierung
ist
Teil
des
Enumerable
Mixins.
p numbers.sort
# => [10, 20, 30, 40, 50]
p hash.sort_by { |k, v| v }
# => [["c", 10], ["b", 50], ["a", 100]]
Hinweis:
Beide
Sortierungsfunktionen
verändern
das
originale
Objekt
nicht.
Wenn
das
originale
Objekt
direkt
sortiert
werden
soll,
gibt
es
jeweils
destruktive
Bang-‐Methoden
dafür
(sort!
bzw.
sort_by!).
©
2011,
Julian
Fischer
und
Clemens
Kofler
23. Verwendung
von
externen
Iteratoren
Es
ist
möglich,
eigenständige
(externe)
Iterator-‐Objekte
zu
verwenden,
die
ähnlich
wie
Iteratoren
in
Java
funktionieren.
Dazu
wird
der
gewünschte
Iterator
ohne
Block
aufgerufen.
enumerator = [1, 2, 3].each
puts enumerator.next # => 1
Diese
Variante
wird
jedoch
eher
selten
verwendet.
lambdas,
procs
und
Blöcke
lambdas
und
procs
sind
Blöcke
von
Code,
die
als
Objekte
durchgereicht
und
dynamisch
ausgeführt
werden
können.
Am
ehesten
sind
sie
mit
Callback-‐Funktionen
in
JavaScript
und
anonymen
inneren
Klassen
in
Java
(z.B.
ActionListener)
zu
vergleichen.
Deklaration
und
Verwendung
greeter = proc { |name| "Hallo #{name}" }
puts greeter.call("Matz") # => "Hallo Matz"
Wie
bereits
erwähnt,
sind
procs
Objekte
und
können
z.B.
als
Parameter
an
Methoden
übergeben
und
dort
mittels
call
aufgerufen
werden:
def output_greeting(greeter_proc, name)
puts greeter_proc.call(name)
end
output_greeting(greeter, "Matz") # => "Hallo Matz"
lambdas
unterscheiden
sich
von
procs
dadurch,
dass
die
Parameter
eines
lambda
verpflichtend
sind:
a_proc = proc { |a| puts "a: #{a}" }
a_proc.call(1) # => a: 1
a_proc.call(1, 2) # => a: 1
a_proc.call # => a:
a_lambda = lambda { |a| puts "a: #{a}" }
a_lambda.call(1) # => a: 1
a_lambda.call(1, 2)
# => wrong number of arguments (2 for 1) (ArgumentError)
a_lambda.call
©
2011,
Julian
Fischer
und
Clemens
Kofler
24. # => wrong number of arguments (0 for 1) (ArgumentError)
Blöcke
Methoden
können
optional
einen
Parameter
als
so
genannten
Block
entgegen
nehmen.
Ein
Beispiel
sind
Iteratoren.
numbers = [1, 2, 3]
numbers.each { |n| puts n }
Der
Abschnitt
{ |n| puts n }
wird
dabei
als
Block
bezeichnet
und
wird
für
jedes
Element
des
Arrays
aufgerufen.
Weitere
Beispiele:
# ohne Block
f = File.open('/Users/clemenskofler/test.txt')
puts f.read
f.close
# mit Block: Ruby öffnet die Datei, lässt uns damit arbeiten
und kümmert sich automatisch um das Schließen der Datei
File.open('/Users/clemenskofler/test.txt') { |f| puts f.read }
Man
kann
auch
selbst
Methoden
mit
Block-‐Parametern
definieren.
def handle_file(file, &block)
f = File.open(file)
block.call(f)
f.close
end
file = '/Users/clemenskofler/test.txt'
handle_file(file) { |f| puts f.read }
Statt
den
Block
direkt
mit
call
aufzurufen,
kann
auch
yield
verwendet
werden.
Dabei
kann
auf
die
explizite
Deklaration
des
Block-‐Parameters
verzichtet
werden.
def handle_file(file)
f = File.open(file)
yield(f)
f.close
end
file = '/Users/clemenskofler/test.txt'
handle_file(file) { |f| puts f.read }
©
2011,
Julian
Fischer
und
Clemens
Kofler
25.
Kontrollstrukturen
Ruby
kennt
ähnliche
Kontrollstrukturen
wie
Java,
um
den
Fluss
des
Programms
zu
steuern.
Boolsche
Operatoren
Ruby
kennt
dieselben
boolschen
Operatoren
wie
Java:
• &&,
and:
logisches
Und
• ||,
or:
logisches
Oder
• !,
not:
logisches
Nicht
• <,
<=,
>,
>=:
kleiner/größer
(gleich)
• ==:
gleich
Die
Operatoren
folgen
den
üblichen
Regeln
der
boolschen
Algebra.
Allerdings
kann
im
Gegensatz
zu
anderen
Sprachen
nicht
nur
ein
boolscher
Wert
sondern
jeder
beliebige
Wert
an
einem
boolschen
Ausdruck
teilnehmen.
In
Ruby
evaluiert
in
einem
boolschen
Ausdruck
jeder
Wert
außer
false
und
nil
auf
true.
Conditionals
(if,
else
etc.)
today = Time.now
if today.wday == 6
puts "Hausarbeit!"
elsif today.wday == 7
puts "Relax"
else
puts "Arbeit"
end
Wie
bei
anderen
Programmiersprachen
sind
die
Abschnitte
elsif
und
else
optional.
Außerdem
kann
bei
negierten
Bedingungen
unless
verwendet
werden:
x = 41
if x != 42
puts "Die Antwort ist 42, nicht #{x}!”
end
©
2011,
Julian
Fischer
und
Clemens
Kofler
26. unless x == 42
puts "Die Antwort ist 42, nicht #{x}!”
end
Hinweis:
unless
+
else
sollte
der
Klarheit
wegen
vermieden
werden.
Als
Kurzform
für
if/else
kann
der
ternäre
Operator
verwendet
werden:
d = today.wday
if d == 6 || d == 7
puts "Wochenende"
else
puts "Noch nicht Wochenende"
end
puts d == 6 || d == 7 ? "Wochenende" : "Noch nicht Wochenende"
Im
Gegensatz
zu
anderen
Sprachen
hat
in
Ruby
auch
ein
if/else-‐Konstrukt
einen
Rückgabewert:
d = today.wday
output = if d == 6 || d == 7
"Wochenende"
else
"Noch nicht Wochenende"
end
puts output
Für
einzelne
if/unless-‐Konstrukte
wird
gerne
die
Inline-‐Variante
verwendet,
wo
die
Bedingung
nachgestellt
wird:
puts "Mach irgendwas Sinnvolles" if today.wday == 6
puts "Noch immer nicht Sonntag" unless today.wday == 7
case/when
Ein
case-‐when-‐Ausdruck
ist
das
Ruby-‐Pendant
zum
aus
Java
bekannten
switch-‐case.
case today.wday
©
2011,
Julian
Fischer
und
Clemens
Kofler
27. when 7
puts "Sonntag"
when 6
puts "Samstag"
else
puts "Immer noch nicht Wochenende :("
end
Für
kurze
Abschnitte
gibt
es
auch
hier
eine
Inline-‐Variante:
case today.wday
when 7 then puts "Sonntag"
when 6 then puts "Samstag"
else
puts "Immer noch nicht Wochenende :("
end
Es
können
auch
mehrere
Werte
in
einem
when
verwendet
werden:
case today.wday
when 6, 7 then puts "Wochenende"
else
puts "Immer noch nicht Wochenende :("
end
Komplexere
case-‐when-‐Varianten
werden
später
behandelt.
Loops
(for,
while
etc.)
Ruby
kennt
verschiedene
Schleifen:
for,
while,
do ... while
und
until.
Diese
funktionieren
im
Wesentlichen
gleich
wie
in
Java.
In
den
meisten
Fällen
werden
jedoch
Iteratoren
(z.B.
each)
vorgezogen,
weil
sie
einfacher
zu
handhaben
sind.
Literaturempfehlungen
Gratis
http://mislav.uniqpath.com/poignant-‐guide/book/
(Kapitel
3+4)
http://ruby-‐doc.org/docs/
(allerlei
Links
zu
Dokumentationen)
http://ruby-‐doc.org/docs/ProgrammingRuby/
(ältere
Version
von
Programming
Ruby)
Kostenpflichtig
http://www.amazon.de/dp/0596516177
(The
Ruby
Programming
Language)
©
2011,
Julian
Fischer
und
Clemens
Kofler
29. Standard-‐Library
und
Gems
Ruby
unterteilt
sich
in
eine
Core-‐
und
Standard-‐Library:
Während
die
Core-‐Library
automatisch
zur
Verfügung
steht,
müssen
Elemente
der
Standard-‐Library
vor
Verwendung
explizit
mittels
require
geladen
werden.
Zusätzlich
liefert
Ruby
seit
Version
1.9
den
Paketmanager
RubyGems
aus
(in
älteren
Ruby-‐Versionen
wurde
dieser
in
der
Regel
manuell
dazu
installiert).
Ein
Gem
ist
ein
Programmpaket,
das
eigenständig
ausgeliefert
und
von
Anwendungen
verwendet
werden
kann.
Standard-‐Library
Verwendung
Pakete
der
Standard-‐Library
können
mittels
require
geladen
und
anschließend
verwendet
werden.
require 'date'
puts Date.today # => 2011-12-15
Dasselbe
Paket
kann
ohne
weiteres
mehrmals
mittels
require
eingebunden
werden:
Tatsächlich
ignoriert
Ruby
mehrfache
Aufrufe.
Verfügbare
Pakete
Eine
Liste
aller
verfügbaren
Pakete
für
die
aktuelle
Ruby-‐Version
(aktuell:
1.9.3)
findet
sich
stets
unter
http://www.ruby-‐doc.org/stdlib.
Status
der
Standard-‐Library
Viele
Pakete
der
Standard-‐Library
sind
veraltet
und/oder
schlecht
gewartet.
Viele
Ruby-‐
Programmierer
haben
daher
Gems
geschrieben,
die
weniger
geeignete
Pakete
der
Standard-‐Library
ersetzen
sollen.
Je
nach
Themenbereich
können
alternative
Lösungen
auf
Ruby
Toolbox
(https://www.ruby-‐toolbox.com/)
und
RubyGems.org
(https://rubygems.org/)
recherchiert
werden.
Gems
Gems
sind
Programmpakete,
die
mithilfe
des
Paketmanagers
RubyGems
installiert
werden
und
anschließend
in
der
Applikation
verwendet
werden
können.
©
2011,
Julian
Fischer
und
Clemens
Kofler
30. Verwendung
Gems
können
entweder
direkt
über
RubyGems
oder
mit
Bundler
verwendet
werden.
require 'rubygems'
require 'activesupport'
puts ''.blank? # => true
Verfügbare
Pakete
Gems
werden
grundsätzlich
auf
https://rubygems.org/
gehostet,
wo
alle
Informationen
(z.B.
Versionen,
Paketabhängigkeiten
etc.)
einsehbar
sind.
Eine
strukturiertere
Auflistung
vieler
Gems
findet
sich
auf
https://www.ruby-‐
toolbox.com/.
Auswahl
passender
Gems
Gems
unterliegen
grundsätzlich
keiner
Qualitätskontrolle,
d.h.
die
Auswahl
geeigneter
Gems
mit
guter
Qualität
obliegt
dem
Programmierer.
Mit
Hilfe
von
Ruby
Toolbox
(https://www.ruby-‐toolbox.com/)
lässt
sich
anhand
einiger
Kriterien
mit
großer
Wahrscheinlichkeit
feststellen,
ob
das
Gem
von
guter
Qualität
ist:
• Hat
das
Gem
eine
verständliche
und
ausführliche
Readme?
• Hat
das
Gem
eine
automatische
Test-‐Suite?
• Ist
das
Gem
von
einem
angesehen
Autor?
• Wird
das
Gem
aktiv
gewartet?
• Wie
lange
gibt
es
das
Gem
bereits?
• Wird
das
Gem
von
vielen
Leuten
verwendet
(häufig
gedownloadet)?
• Wird
das
Gem
auf
GitHub
(de-‐facto-‐Standard)
gehostet?
• Hat
das
Gem
viele
offene
Bugmeldungen
auf
GitHub?
Empfohlene
Gems
Im
Folgenden
sind
einige
gängige
Anwendungsfälle
sowie
passende,
häufig
verwendete
Gems
zusammengetragen.
File
Uploads
(+
Image
Processing)
• Carrierwave
• Paperclip
User
Authentifizierung
und
Autorisierung
©
2011,
Julian
Fischer
und
Clemens
Kofler
31. • Devise
• Sorcery
• OmniAuth
(externe
Auth
Provider,
z.B.
Facebook)
• CanCan
Formulare
• Formtastic
• SimpleForm
Permalinks
• friendly_id
XML
• hpricot
(simpel)
• Nokogiri
(komplexer)
SOAP
• handsoap
• savon
HTTP
• httparty
• faraday
• curb
Payment
• activemerchant
Tagging
• acts_as_taggable_on
Testing
• rspec
• Capybara
(+
Cucumber)
• capybara_webkit
• FactoryGirl
• DatabaseCleaner
• Timecop
• FakeWeb
• vcr
• Faker
©
2011,
Julian
Fischer
und
Clemens
Kofler
32. Automatisierung
• guard
• foreman
Internationalisierung
• i18n
• globalize
State
Machine
• AASM
(Acts
As
State
Machine)
Paginierung
• will_paginate
• kaminari
Deployment
• Capistrano
• Vlad
Monitoring
• Exceptional
• Airbrake
• NewRelic
• Scout
(Lokaler)
Webserver
• Mongrel
• pow
• unicorn
• thin
Log
Analyse
• request-‐log-‐analyzer
Code
Qualität
• SimpleCov
/
rcov
• metric_fu
(+
darin
enthaltene
Gems)
©
2011,
Julian
Fischer
und
Clemens
Kofler
33. Bundler
Bundler
wird
verwendet,
um
Abhängigkeiten
unter
verschiedenen
Gems
zu
verwalten
und
aufzulösen.
Bevor
Bundler
verwendet
wurde,
gab
es
häufig
Versionskonflikte,
weil
der
RubyGems
Paketmanager
lediglich
einen
unzureichenden
Algorithmus
zur
Auflösung
von
Paketabhängigkeiten
bereitstellt.
Wir
halten
an
dieser
Stelle
eine
dedizierte
Einführung
in
Bundler
nicht
für
sinnvoll,
weil
die
Problematik,
die
Bundler
löst,
sich
erst
in
der
tatsächlichen
Entwicklung
mit
Ruby
erschließt.
Dennoch
wollten
wir
den
Dependency
Manager
an
dieser
Stelle
erwähnen,
damit
zumindest
der
Begriff
bekannt
ist.
Literaturempfehlungen
Gratis
http://www.mikeperham.com/2010/11/22/the-‐ruby-‐stdlib-‐is-‐a-‐ghetto/
https://www.ruby-‐toolbox.com/
https://rubygems.org/
http://gembundler.com/
http://railscasts.com/episodes/201-‐bundler
©
2011,
Julian
Fischer
und
Clemens
Kofler
34. Objektorientierte
Programmierung
mit
Ruby
–
Grundlagen
Klassen
und
Instanzen
Ruby
ist
–
wie
Java
–
eine
klassenbasierte
objektorientierte
Sprache.
Klassen
werden
definiert
und
dienen
als
Vorlage
für
konkrete
Objektinstanzen.
class Person
end
Neue
Instanzen
werden
erzeugt,
indem
die
Methode
new
auf
die
Klasse
aufgerufen
wird.
matz = Person.new
p matz # => #<Person:0x100139b50>
Methoden
Methoden
definieren
die
Funktionalitäten
von
Klassen
und
Objekten.
Man
unterscheidet
zwischen
Klassen-‐
und
Instanzmethoden.
Instanzmethoden
Instanzmethoden
sind
Methoden,
die
innerhalb
einer
Instanz
zur
Verfügung
stehen.
class Person
def says_hello
puts 'Hello!'
end
end
matz = Person.new
matz.says_hello
Die
Methode
initialize
ist
ein
Spezialfall
einer
Instanzmethode
und
dient
als
Konstruktor.
Hier
wird
die
Objektinstanz
für
die
Verwendung
vorbereitet.
class Person
def initialize
puts 'in initialize'
end
end
©
2011,
Julian
Fischer
und
Clemens
Kofler
35. matz = Person.new
Klassenmethoden
Klassenmethoden
sind
Methoden,
die
für
eine
Klasse
zur
Verfügung
stehen.
class Person
def self.test
puts 'Person.test'
end
end
Person.test
Hash-‐Parameter
Häufig
wird
in
Ruby
ein
Hash
als
letzter
Parameter
einer
Methode
verwendet.
Besonders
bei
Ruby
on
Rails
nennt
man
diesen
gern
“options
hash”.
def content_tag(name, content, options = {})
html = "<#{name}"
options.each do |key, value|
html << %( #{key}="#{value}")
end
html << ">#{content}</#{name}>"
html
end
puts content_tag(:p, 'Hello', { :class => 'greeting' })
# => <p class="greeting">Hello</p>
Wenn,
wie
in
diesem
Fall,
der
Hash
der
letzte
Parameter
des
Methodenaufrufs
ist,
werden
die
geschwungenen
Klammern
üblicherweise
weggelassen:
puts content_tag(:p, 'Hello', :class => 'greeting)
# => <p class="greeting">Hello</p>
Multi-‐Parameter
In
Ruby
ist
es
möglich,
mehrere
Parameter
zu
übergeben,
und
diese
in
einem
Array
statt
als
einzelne
Parameter
engegenzunehmen.
def values_in_hash(hash, *fields)
fields.map { |field| hash[field] }
©
2011,
Julian
Fischer
und
Clemens
Kofler
36. end
hash = { :a => 1, :b => 2, :c => 3, :d => 4 }
p values_in_hash(hash, :a, :c) # => [1, 3]
Auch
der
umgekehrte
Weg
ist
möglich:
Man
kann
die
Werte
in
einem
Array
als
mehrere
Einzelparameter
übergeben:
hash = { :a => 1, :b => 2, :c => 3, :d => 4 }
fields = [:a, :c]
p hash.values_at(*fields) # => [1, 3]
Wenn
der
*
Operator
einem
Array
vorangestellt
wird,
nennt
man
ihn
“Splat”.
Variablen
Wie
bereits
zu
Anfang
erwähnt,
unterscheidet
Ruby
zwischen
Instanz-‐
(beginnen
mit
@)
und
Klassenvariablen
(beginnen
mit
@@).
Instanzvariablen
Instanzvariablen
stehen
innerhalb
einer
Instanz
zur
Verfügung.
class Person
def initialize(name)
@name = name
end
def says_hello
puts "Hello from #{@name}!"
end
end
matz = Person.new('Matz')
matz.says_hello
Accessors
Ruby
verwendet
einen
Accessor-‐/Property-‐basierten
Ansatz,
um
Instanzvariablen
nach
außen
zur
Verfügung
zu
stellen.
class Person
attr_accessor :name
©
2011,
Julian
Fischer
und
Clemens
Kofler
37. # attr_reader :name
# attr_writer :name
end
matz = Person.new
matz.name = 'Matz'
puts matz.name
# ohne Accessor
class Person
def name
@name
end
def name=(new_name)
@name = new_name
end
end
matz = Person.new
matz.name = 'Matz'
puts matz.name
Ein
Accessor
greift
dabei
immer
auf
die
Instanzvariable
mit
demselbem
Namen
zu.
class Person
attr_accessor :name
def initialize(name)
@name = name
end
end
matz = Person.new('Matz')
puts matz.name
matz.name = 'Yukihiro Matsumoto'
puts matz.name
©
2011,
Julian
Fischer
und
Clemens
Kofler
38. Access
Control
(Zugriffskontrolle)
Methoden
können
vor
dem
Zugriff
geschützt
werden.
Dafür
stehen
die
Deklarationen
protected
und
private
zur
Verfügung.
Ohne
explizite
Deklaration
sind
alle
Methoden
public.
class Person
def dont_call_me
puts "Don't call me!"
end
private :dont_call_me
end
Person.new.dont_call_me # => NoMethodError: private method
‘dont_call_me’ called for #<Person:0x1001352f8>
Es
ist
auch
möglich,
mehrere
Methoden
auf
einmal
als
public/protected/private
zu
deklarieren:
class Person
public
# ... everything's public from now on
protected
# ... now protected
private
# ... now private
public
# ... and public again
end
Hinweis:
protected
und
private
unterscheiden
sich
marginal
und
können
in
der
Regel
synonym
betrachtet
werden.
Vererbung
Jede
Klasse
in
Ruby
kann
von
einer
anderen
Klasse,
der
so
genannten
Superklasse,
erben.
Wenn
eine
Klasse
keine
Superklasse
hat,
erbt
sie
von
Object
(wie
in
Java).
Der
Vererbungsoperator
ist
<.
class Person
end
©
2011,
Julian
Fischer
und
Clemens
Kofler
39. class Programmer < Person
end
Methoden
Klassen
erben
alle
Methoden
ihrer
Superklasse.
class Person
def initialize(name)
@name = name
end
def about_me
@name
end
end
class Programmer < Person
end
matz = Programmer.new('Matz')
puts matz.about_me
Klassenmethoden
und
Accessors
werden
ebenso
wie
Instanzmethoden
geerbt.
super
Klassen
können
Methoden
ihrer
Superklasse
überschreiben
und
die
originale
Methode
bei
Bedarf
mit
super
aufrufen.
class Person
def initialize(name)
@name = name
end
def about_me
@name
end
end
©
2011,
Julian
Fischer
und
Clemens
Kofler
40. class Programmer < Person
def about_me
"#{super} (Programmer)"
end
end
matz = Programmer.new('Matz')
puts matz.about_me
Literaturempfehlungen
Gratis
http://langref.org/ruby/oop
http://zetcode.com/lang/rubytutorial/oop/
http://bandwagonblog.wordpress.com/2009/01/12/ruby-‐oop-‐intro/
©
2011,
Julian
Fischer
und
Clemens
Kofler
41. Objektorientierte
Programmierung
mit
Ruby
–
Fortgeschrittene
Themen
Ruby
Objektmodell
Alles
in
Ruby
ist
ein
Objekt
–
selbst
die
vermeintlich
“primitiven
Datentypen”
wie
Zahlen.
Die
Klasse
jedes
Objekts
kann
mit
.class
überprüft
werden:
puts 1.class # => Fixnum
puts 1.5.class # => Float
puts 'a'.class # => String
puts [].class # => Array
puts ({}).class # => Hash
Selbst
Klassen
sind
Objekte
–
und
zwar
vom
Typ
Class.
puts Array.class # => Class
puts Hash.class # => Class
Klassenhierarchien
Die
Hierarchie
einer
Klasse
kann
mit
der
Methode
superclass
geprüft
werden.
puts Array.superclass # => Object
puts Object.superclass # => BasicObject
puts BasicObject.superclass # => nil
Alle
inkludierten
Module
und
Superklassen
sind
mit
der
Methode
ancestors
einsehbar.
p Array.ancestors
# => [Array, Enumerable, Object, Kernel, BasicObject]
Module
Ruby
Module
sind
am
ehesten
mit
Java
Interfaces
zu
vergleichen.
Der
wesentliche
Unterschied
besteht
darin,
dass
Ruby
Module
in
der
Regel
nicht
nur
ein
Interface
zur
Verfügung
stellen,
sondern
auch
eine
Implementierung.
module Naming
def full_name
"#{first_name} #{last_name}"
end
©
2011,
Julian
Fischer
und
Clemens
Kofler
42. end
class Person
attr_reader :first_name, :last_name
include Naming
def initialize(first_name, last_name)
@first_name = first_name
@last_name = last_name
end
end
matz = Person.new('Yukihiro', 'Matsumoto')
puts matz.full_name # => Yukihiro Matsumoto
Person
inkludiert
das
Modul
Naming.
Dadurch
wird
implizit
ein
Vertrag
geschlossen,
in
dem
Person
garantiert,
die
Methoden
first_name
und
last_name,
die
von
Naming
benötigt
werden,
zur
Verfügung
zu
stellen.
Wir
haben
einen
derartigen
Vertrag
bereits
beim
Modul
Enumerable
gesehen:
Jede
Klasse,
die
Enumerable
verwenden
will,
garantiert,
dass
seine
Methode
each
zur
Verfügung
gestellt
wird,
auf
der
die
restlichen
Iteratoren
aufsetzen.
So
kann
eine
jede
Klasse
iterierbar
gemacht
werden.
class PersonRepository
include Enumerable
def initialize(people)
@people = people
end
def each(&block)
@people.each { |person| block.call(person) }
end
end
class Person
©
2011,
Julian
Fischer
und
Clemens
Kofler
43. attr_reader :name
def initialize(name)
@name = name
end
def inspect
name
end
end
people = [Person.new('Matz'), Person.new('Clemens'),
Person.new('Julian')]
person_repository = PersonRepository.new(people)
p person_repository.collect { |person| person.name }
# => ["Matz", "Clemens", "Julian"]
p person_repository.sort_by { |person| person.name }
# => [Clemens, Julian, Matz]
Methoden
Zum
Verständnis
von
Rubys
Objektmodell
ist
es
essentiell,
zu
verstehen,
wie
Methoden
aufgerufen
werden.
Messages
und
Receiver
Wenn
man
in
Ruby
vom
Aufruf
einer
Methode
spricht,
meint
man
streng
genommen,
dass
eine
Message
(Nachricht)
mit
einem
bestimmten
Namen
an
ein
Objekt
–
den
so
genannten
Receiver
(Empfänger)
gesendet
wird:
name = "Matz"
puts name.length
In
diesem
Beispiel
wird
eine
Message
mit
dem
Namen
length
an
das
Objekt
name
gesendet.
Das
Objekt
name
ist
somit
der
Receiver
der
Message
length.
©
2011,
Julian
Fischer
und
Clemens
Kofler
44. self
Wenn
bei
einem
Methodenaufruf
kein
expliziter
Receiver
angegeben
wird,
sendet
Ruby
die
Nachricht
automatisch
an
das
spezielle
Objekt
self.
self
wird
dabei
je
nach
Kontext
angepasst.
Das
kann
in
einem
kurzen
Testprogramm
überprüft
werden:
p self # => main
class Test
p self # => Test
def test
p self # => #<Test:0x100132558>
end
end
Test.new.test
Es
sind
drei
verschiedene
Kontexte
von
self
sichtbar:
• Außerhalb
jedes
Kontextes
ist
self
an
das
spezielle
Objekt
main
gekoppelt.
• Innerhalb
des
Körpers
einer
Klasse
entspricht
self
der
Klasse
selbst.
Von
daher
kommt
die
Möglichkeit,
Klassenmethoden
zu
definieren:
Tatsächlich
werden
dabei
Methoden
auf
dem
self-‐Objekt
definiert.
• Innerhalb
einer
Instanzmethode
entspricht
das
self-‐Objekt
der
konkreten
Instanz.
Um
den
Fluss
seines
Programms
zu
verstehen,
sollte
man
sich
zu
jeder
Zeit
bewusst
sein,
an
welchen
Kontext
self
gerade
gebunden
ist.
Duck
Typing
Wie
bereits
erwähnt,
ist
Ruby
dynamisch
typisiert:
Der
Wert
von
Variablen
und
Parametern
wird
bei
Zuweisung
festgelegt
und
kann
sich
auch
jederzeit
ändern.
Es
gibt
keinen
Compiler,
der
hilft,
für
Parameter
von
Methoden
bestimmte
Typen
zu
forcieren.
Man
kann
durchaus
beim
Methodenaufruf
die
Typen
von
Parametern
prüfen:
class Duck
def quack
puts "Quack!"
end
©
2011,
Julian
Fischer
und
Clemens
Kofler
45. end
class Goose
def quack
puts "Quock!"
end
end
def quacker(duck)
raise ArgumentError.new('I can only handle Duck objects')
unless duck.is_a?(Duck)
duck.quack
end
quacker(Duck.new) # Quack!
quacker(Goose.new)
# => ArgumentError: I can only handle Duck objects
Durch
die
strenge
Typprüfung
wird
die
Methode
unnötig
eingeschränkt:
Die
einzige
Voraussetzung,
damit
die
Methode
verwendet
werden
kann,
ist,
dass
das
übergebene
Objekt
die
Methode
quack
zur
Verfügung
stellt.
Daher
kann
auf
genau
diese
Fähigkeit
geprüft
werden:
def quacker(quacking)
raise ArgumentError.new('I can only handle quacking
objects') unless quacking.respond_to?(:quack)
quacking.quack
end
quacker(Duck.new) # => Quack!
quacker(Goose.new) # => Quock!
Es
wird
ein
implizites
Interface
angenommen
und
gegen
dieses
Interface
statt
gegen
eine
Implementierung
programmiert.
Diese
Technik
heißt
Duck
Typing:
In
other
words,
don't
check
whether
it
IS-‐a
duck:
check
whether
it
QUACKS-‐like-‐a
duck,
WALKS-‐like-‐a
duck,
etc,
etc,
depending
on
©
2011,
Julian
Fischer
und
Clemens
Kofler
46. exactly
what
subset
of
duck-‐like
behaviour
you
need
to
play
your
language-‐games
with.
Alex
Martelli
(2000),
http://en.wikipedia.org/wiki/Duck_Typing#History
In
den
meisten
Fällen
ist
es
besser,
gegen
des
Interface
eines
Objekts
zu
programmieren
statt
gegen
dessen
Implementierung.
Interne
und
externe
APIs
Wie
schon
im
Kapitel
Zugriffskontrolle
erwähnt,
dienen
die
Deklarationen
protected
und
private
dazu,
den
Zugriff
auf
Methoden
von
außen
zu
beschränken.
Man
spricht
hier
von
der
Unterscheidung
zwischen
einer
externen
(öffentlichen)
API
und
einer
internen
(privaten)
API:
Die
externe
API
darf
von
fremden
Objekten
verwendet
werden,
die
interne
API
nur
vom
Objekt
selbst.
Zugriff
auf
die
interne
API
mittels
send
Gemäß
dem
Prinzip,
dass
in
Ruby
alles
jederzeit
möglich
ist,
kann
unabhängig
von
allen
Zugriffsdeklarationen
jederzeit
auf
alle
Methoden
zugegriffen
werden.
Dafür
dient
die
Methode
send.
class Person
def dont_call_me
puts "Don't call me!"
end
private :dont_call_me
end
Person.new.dont_call_me
# => NoMethodError: private method ‘dont_call_me’ ...
Person.new.send(:dont_call_me) # => Don't call me!
Hinweis:
Wenn
die
Methode
send
aus
irgendeinem
Grund
überschrieben
wurde
und
nicht
zur
Verfügung
steht,
kann
stattdessen
__send__
verwendet
werden.
Wann
sollte
man
send
nicht
verwenden?
Der
Zugriff
mittels
send
sollte
generell
nur
dann
erfolgen,
wenn
externer
Code
–
d.h.
z.B.
Code
des
verwendeten
Frameworks
(Rails,
Sinatra,
…)
–
verwendet
wird
und
geschützte
Methoden
aufgerufen
werden
sollen.
©
2011,
Julian
Fischer
und
Clemens
Kofler