summaryrefslogtreecommitdiffhomepage
path: root/de-de/ruby-de.html.markdown
blob: 8025a8c0eb57c296672a3a81b75a303918d376c1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
---
language: ruby
filename: ruby-de.rb
contributors:
  - ["David Underwood", "http://theflyingdeveloper.com"]
  - ["Joel Walden", "http://joelwalden.net"]
  - ["Luke Holder", "http://twitter.com/lukeholder"]
  - ["Tristan Hume", "http://thume.ca/"]
  - ["Nick LaMuro", "https://github.com/NickLaMuro"]
  - ["Marcos Brizeno", "http://www.about.me/marcosbrizeno"]
  - ["Ariel Krakowski", "http://www.learneroo.com"]
  - ["Dzianis Dashkevich", "https://github.com/dskecse"]
  - ["Levi Bostian", "https://github.com/levibostian"]
  - ["Rahil Momin", "https://github.com/iamrahil"]
  - ["Gabriel Halley", "https://github.com/ghalley"]
  - ["Persa Zula", "http://persazula.com"]
  - ["Jake Faris", "https://github.com/farisj"]
  - ["Corey Ward", "https://github.com/coreyward"]
  - ["Jannik Siebert", "https://github.com/janniks"]
  - ["Keith Miyake", "https://github.com/kaymmm"]
translators:
  - ["Christian Albrecht", "https://github.com/coastalchief"]
  - ["Dennis Keller", "https://github.com/denniskeller"]
  - ["Paul Götze", "https://gitub.com/paulgoetze"]
lang: de-de
---

```ruby
# Das ist ein Kommentar

=begin
Das ist ein mehrzeiliger Kommentar.
Die Anfangszeile muss mit "=begin" beginnen
und die Endzeile muss mit "=end" beginnen. 

Alternativ kannst du jede Zeile in einem 
mehrzeiligen Kommentar mit dem # Zeichen beginnen. 
=end

# In Ruby ist (fast) alles ein Objekt.
# Das schließt Zahlen ein...
3.class #=> Integer

# ...und Zeichenketten (Strings)...
"Hallo".class #=> String

# ...und sogar Methoden!
"Hallo".method(:class).class #=> Method

# Simple Arithmetik
1 + 1 #=> 2
8 - 1 #=> 7
10 * 2 #=> 20
35 / 5 #=> 7
2 ** 5 #=> 32
5 % 3 #=> 2

# Bitweise Operatoren
3 & 5 #=> 1
3 | 5 #=> 7
3 ^ 5 #=> 6

# Arithmetik ist aber eigentlich nur syntaktischer Zucker
# um eine Methode eines Objekts aufzurufen
1.+(3) #=> 4
10.* 5 #=> 50
100.methods.include?(:/) #=> true

## Spezielle Werte sind Objekte
nil # Equivalent zu null in anderen Sprachen
true # Wahrheitswert
false # Falschheitswert

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

# Gleicheit
1 == 1 #=> true
2 == 1 #=> false

# Ungleichheit
1 != 1 #=> false
2 != 1 #=> true

# Neben false selbst, ist nil der einzige andere 
# zu Falsch evaluierende Wert

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

# Weitere Vergleiche
1 < 10 #=> true
1 > 10 #=> false
2 <= 2 #=> true
2 >= 2 #=> true

# Kombinierter Vergleichsoperator (gibt `1` zurück wenn das erste Argument 
# größer ist, und `-1`, wenn das zweite Argument größer ist, sonst `0`)
1 <=> 10 #=> -1 (1 < 10)
10 <=> 1 #=> 1 (10 > 1)
1 <=> 1 #=> 0 (1 == 1)

### Logische Operatoren
true && false #=> false
true || false #=> true

# Es gibt alternative Versionen der logischen Operatoren mit niedrigerer
# Wertigkeit. Diese werden meistens zur Flusskontrolle eingesetzt, um
# verschiedenen Ausdrücke zu verketten bis einer true oder false zurück
# liefert.

# `do_something_else` wird nur ausgewertet wenn `do_something` true ist.
do_something() and do_something_else()
# `log_error` wird nur ausgewertet wenn `do_something` false ist.
do_something() or log_error()

# String Interpolation

placeholder = 'Ruby'
"Ich kann in #{placeholder} Platzhalter mit doppelten Anführungszeichen füllen."
#=> "Ich kann in Ruby Platzhalter mit doppelten Anführungszeichen füllen."

# Du kannst Strings mit `+` verbinden, nicht jedoch mit anderen Typen
'hallo ' + 'Welt'  #=> "hallo Welt"
'Hallo ' + 3 #=> TypeError: no implicit conversion of Integer into String
'hallo ' + 3.to_s #=> "hallo 3"
"hallo #{3}" #=> "hallo 3"

# ...oder Strings mit Operatoren kombinieren
'hallo ' * 3 #=> "hallo hallo hallo "

# ...oder Strings an andere Strings anhängen
'hallo' << ' Welt' #=> "hallo Welt"

# Du kannst Text mit einer neuen Zeile am Ende ausgeben
puts "Ich gebe Text aus!"
#=> Ich gebe Text aus!
#=> nil

# ...oder Text ohne einen Zeilenumbruch ausgeben
print "Ich gebe Text aus!"
#=> "Ich gebe Text aus!" => nil

# Variablen
x = 25 #=> 25
x #=> 25

# Beachte, dass Zuweisungen den zugewiesenen Wert zurückgeben.
# D.h. du kannst mehrfache Zuweisungen machen.

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

# Nutze snake_case für Variablennamen.
snake_case = true

# Nutze verständliche Variablennamen.
path_to_project_root = '/guter/Name/'
m = '/schlechter/Name/'


# Symbole sind unveränderliche, wiederverwendbare Konstanten, welche intern
# als Integer repräsentiert werden. Sie werden häufig anstelle von Strings
# verwendet, um semantisch sinnvoll Werte zu übermitteln.
# Symbols werden mit dem Doppelpunkt gekennzeichnet.

:pending.class #=> Symbol

status = :pending

status == :pending #=> true

status == 'pending' #=> false

status == :approved #=> false

# Strings können in Symbole konvertiert werden und umgekehrt.
status.to_s #=> "pending"
"argon".to_sym #=> :argon

# Arrays

# Das ist ein Array.
array = [1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5]

# Array können verschiedene Typen beinhalten
[1, 'hello', false] #=> [1, "hello", false]

## Arrays könnenindiziert werden.

# Von vorne...
array[0] #=> 1
array.first #=> 1
array[12] #=> nil

# ...oder von hinten...
array[-1] #=> 5
array.last #=> 5

# ...oder mit einem Startindex und einer Länge...
array[2, 3] #=> [3, 4, 5]

# ...oder mit einem Range...
array[1..3] #=> [2, 3, 4]

# Du kanns ein Array umkehren.
# Gib ein neues Array mit umgkehrten Werten zurück
[1,2,3].reverse #=> [3,2,1]

# Kehre ein Array an Ort und Stelle um, um die Variable mit den 
# umgekehrten Werten zu aktualisieren.
a = [1,2,3]
a.reverse! #=> a==[3,2,1] wegen des Aufrufs von reverse mit Ausrufezeichens ('!')

# Wie bei der Arithmetik, ist Zugriff mit [index] nur 
# syntaktischer Zucker für den Aufruf der `[]` Methode auf dem Objekt.
array.[] 0 #=> 1
array.[] 12 #=> nil

# Du kannst Werte zu einem Array hinzufügen...
array << 6 #=> [1, 2, 3, 4, 5, 6]
# Oder so
array.push(6) #=> [1, 2, 3, 4, 5, 6]

# ...und testen ob ein Element schon vorhanden ist
array.include?(1) #=> true

# Hashes sind Rubys Hauptdatenstruktur for Schlüssel/Wert Paare.
# Hashes werden durch geschweifte Klammern gekennzeichnet.
hash = { 'Farbe' => 'grün', 'Nummer' => 5 }

hash.keys #=> ['farbe', 'nummer']

# Hashes can be quickly looked up by key.
hash['Farbe'] #=> "grün"
hash['Nummer'] #=> 5

# Abfragen eines nicht vorhandenen Schlüssels, gibt nil zurück. 
hash['nicht vorhanden'] #=> nil

# Wenn du Symbole als Schlüssel in einem Hash verwendest, kannst du
# eine alternative Syntax verwenden.
hash = { :defcon => 3, :action => true }
hash.keys #=> [:defcon, :action]

hash = { defcon: 3, action: true }
hash.keys #=> [:defcon, :action]

# Testen ob ein Schlüssel oder Wert im Hash existiert
hash.key?(:defcon) #=> true
hash.value?(3) #=> true

# Tipp: Arrays und Hashes sind Enumerables!
# Sie haben viele nützliche Methoden gemein, wie each, map, count, und andere.

# Kontrolstrukturen

# Bedingungen
if true
  'wenn Bedingung'
elsif false
  'sonst wenn, optional'
else
  'sonst, auch optional'
end

# Wenn eine Kontrollstruktur keinen Code-Block, sondern einen einzigen 
# Ausdruck ausführt, dann kannst du die nachgestellte if-Notation verwenden
warnings = ['Nachname fehlt', 'Adresse zu kurz']
puts("Vorhandene Warnungen:\n" + warnings.join("\n"))  if !warnings.empty?

# Formuliere die Bedingung um, wenn sich `unless` besser liest als `if`
puts("Vorhandene Warnungen:\n" + warnings.join("\n")) unless warnings.empty?

# Schleifen
# Traditionell ist das Benutzen von `for` Schleifen in Ruby eher unüblich.
# Stattdessen werden diese mit Hilfe von Enumerables implementiert, was mit
# dem Aufrufen von `each` einhergeht.
(1..5).each do |counter|
  puts "Iteration #{counter}"
end

# Was in etwa das selbe ist wie Folgendes (selten in Ruby zu sehen).
for counter in 1..5
  puts "Iteration #{counter}"
end

# Das `do |variable| ... end` Konstrukt wird `block` genannt. 
# Blocks sind vergleichbar mit Lambdas, anonymen Funktionen 
# oder Closures in anderen Programmiersprachen.
# Sie können als Objekte übergeben, aufgerufen oder als Methoden 
# zugewiesen werden.

# Die `each` Methode eines Ranges führt den Block einmal für jedes 
# Element des Ranges aus. 
# Dem Block wird eine counter Variable als Parameter übergeben.

# Du kannst einen Block auch mit geschweiften Klammern schreiben.
(1..5).each { |counter| puts "Iteration #{counter}" }

# Each kann auch über den Inhalt von Datenstrukturen iterieren.
array.each do |element|
  puts "#{element} is Teil des Arrays"
end

hash.each do |key, value|
  puts "#{key} ist #{value}"
end

# Um auf den Laufindex zuzugreifen kannst du `each_with_index` verwenden
# und eine index Variable definieren. 
array.each_with_index do |element, index|
  puts "#{element} ist Nummer #{index} im Array"
end

counter = 1
while counter <= 5 do
  puts "Iteration #{counter}"
  counter += 1
end
#=> Iteration 1
#=> Iteration 2
#=> Iteration 3
#=> Iteration 4
#=> Iteration 5

# Es gibt einige andere hilfreiche Schleifenfunktionen in Ruby.
# Wie etwa 'map', 'reduce', 'inject' und viele andere mehr. 
# Map zum Beispiel iteriert über das Array, führt für jedes Element 
# die Anweisungen aus, 
# die im Block definiert sind und gibt ein völlig neues Array zurück.
array = [1,2,3,4,5]
doubled = array.map do |element|
  element * 2
end
puts doubled
#=> [2,4,6,8,10]
puts array
#=> [1,2,3,4,5]

# Case Konstruct
grade = 'B'

case grade
when 'A'
  puts 'So wird’s gemacht'
when 'B'
  puts 'Viel Glück beim nächsten Mal'
when 'C'
  puts 'Das kannst du besser'
when 'D'
  puts 'Gerade so durch'
when 'F'
  puts 'Durchgefallen!'
else
  puts 'Anderes Bewertungssystem, was?'
end
#=> "Viel Glück beim nächsten Mal"

# Case kann auch Ranges benutzen
grade = 82
case grade
when 90..100
  puts 'Hurra!'
when 80...90
  puts 'OK gemacht'
else
  puts 'Durchgefallen!'
end
#=> "OK gemacht"

# Fehlerbehandlung
begin
  # Code der einen Fehler wirft...
  raise NoMemoryError, 'Dein Speicher ist voll.'
rescue NoMemoryError => exception_variable
  puts 'NoMemoryError ist aufgetreten', exception_variable
rescue RuntimeError => other_exception_variable
  puts 'RuntimeError ist aufgetreten'
else
  puts 'Das wird ausgeführt, wenn keine Fehler geworfen wurden'
ensure
  puts 'Dieser Code wird immer ausgeführt, egal was vorher passiert'
end

# Methoden

def double(x)
  x * 2
end

# Methoden (und Blocks) geben implizit den Wert des letzten Anweisung zurück.
double(2) #=> 4

# Klammern sind optional wenn die Anweisung dadurch nicht mehrdeutig wird.
double 3 #=> 6

double double 3 #=> 12

def sum(x, y)
  x + y
end

# Die Argumente einer Methode werden durch ein Komma getrennt.
sum 3, 4 #=> 7

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

# yield
# Alle Methoden haben implizit einen optionalen block Parameter.
# Dieser kann durch das Schlüsselwort 'yield' ausgeführt werden.
def surround
  puts '{'
  yield
  puts '}'
end

surround { puts 'hallo Welt' }

#=> {
#=> hallo Welt
#=> }

# Blocks können in ein 'Proc' Objekt umgewandelt werden. 
# Dieses ist eine Art Container um den Block und erlaubt ihn an eine 
# andere Methode zu übergeben, ihn in einen anderen Gültigkeitsbereicht 
# einzubinden oder ihn andersweitig zu verändern.
# Am häufigsten findet man dies bei Parameterlisten von Methoden, in Form 
# eines letzten '&block' Parameters, der den Block – wenn es einen gibt – 
# entgegen nimmt und ihn in ein 'Proc' umwandelt. Die Benennung '&block' ist 
# hier nur eine Konvention; es würde genauso mit '&pineapple' funktionieren. 
def guests(&block)
  block.class #=> Proc
  block.call(4)
end

# Die 'call' Methode eines Proc ist ganz ähnlich zum Aufruf von 'yield', wenn 
# ein Block vorhanden ist. Die Argumente, die 'call' übergeben werden, werden 
# als Argumente and den Block weitergereicht.

guests { |n| "Du hast #{n} Gäste." }
# => "Du hast 4 Gäste."

# Du kannst eine Liste von Argumenten übergeben, die dann in ein Array 
# umgewandelt werden. Dafür gibt es den splat-Operator (`*`).
def guests(*array)
  array.each { |guest| puts guest }
end

# Destrukturierung

# Ruby destrukturiert Arrays automatisch beim Zuweisen mehrerer Variablen.
a, b, c = [1, 2, 3]
a #=> 1
b #=> 2
c #=> 3

# In manchen Fällen will man den splat-Operator (`*`) verwenden um ein Array in
# eine Liste zu destrukturieren.
ranked_competitors = ["John", "Sally", "Dingus", "Moe", "Marcy"]

def best(first, second, third)
  puts "Gewinner sind #{first}, #{second} und #{third}."
end

best *ranked_competitors.first(3) #=> Gewinner sind John, Sally and Dingus.

# Der splat-Operator kann auch in Parametern verwendet werden.
def best(first, second, third, *others)
  puts "Gewinner sind #{first}, #{second} und #{third}."
  puts "Es gab #{others.count} andere Teilnehmer."
end

best *ranked_competitors 
#=> Gewinner sind John, Sally und Dingus.
#=> Es gab 2 andere Teilnehmer.

# Per Konvention enden alle Methoden, die einen Wahrheitswert zurück geben, mit einem
# Fragezeichen.
5.even? #=> false
5.odd? #=> true

# Wenn ein Methodenname mit einem Ausrufezeichen endet, dann tut diese Methode 
# per Konvention etwas Destruktives, wie z.B. das aufrufende Objekt zu 
# verändern.
# Viele Mehtoden haben eine !-Version um eine direkte Änderung zu machen und 
# eine Nicht-!-Version, die ein neues Objekt mit den Veränderungen zurück gibt.
company_name = "Dunder Mifflin"
company_name.upcase #=> "DUNDER MIFFLIN"
company_name #=> "Dunder Mifflin"
# Diesmal verändern wir company_name direkt.
company_name.upcase! #=> "DUNDER MIFFLIN"
company_name #=> "DUNDER MIFFLIN"

# Klassen

# Du kannst eine Klasse mit dem Schlüsselwort 'class' definieren.
class Human

  # Eine Klassenvariable. Sie wird von allen Instanzen einer Klasse geteilt.
  @@species = 'H. sapiens'

  # Konstruktor bzw. Initializer
  def initialize(name, age = 0)
    # Weise das Argument der Instanzvariable 'name' zu.
    @name = name
    # Wenn kein 'age' angegeben wurde wird der Standartwert aus der Argumentenlist verwendet.
    @age = age
  end

  # Setter Methode
  def name=(name)
    @name = name
  end

  # Getter Methode
  def name
    @name
  end

  # Getter & Setter können auch kürzer mit der attr_accessor Methode erstellt werden.
  attr_accessor :name

  # Getter & Setter Methoden können auch einzeln erstellt werden.
  attr_reader :name
  attr_writer :name

  # Eine Klassenmethode unterscheidet sich durch ein 'self' von einer 
  # Instanzmethode.
  # Sie kann nur auf der Klasse und nicht auf einer Instanz der Klasse 
  # aufgerufen werden.  
  def self.say(msg)
    puts msg
  end

  def species
    @@species
  end
end

# Instanziieren einer Klasse
jim = Human.new('Jim Halpert')
dwight = Human.new('Dwight K. Schrute')

# Du kannst die Methoden des erstellten Objekts aufrufen.
jim.species #=> "H. sapiens"
jim.name #=> "Jim Halpert"
jim.name = "Jim Halpert II" #=> "Jim Halpert II"
jim.name #=> "Jim Halpert II"
dwight.species #=> "H. sapiens"
dwight.name #=> "Dwight K. Schrute"

# Aufrufen einer Klassenmethode
Human.say('Hi') #=> "Hi"

# Der Gültigkeitsbereich einer Variablen wird durch ihren Namen definiert.
# Variablen, die mit $ beginnen sind global gültig.
$var = "Ich bin eine globale Variable"
defined? $var #=> "global-variable"

# Variablen, die mit @ beginnen, sind innerhalb einer Instanz gültig.
@var = "Ich bin eine Instanzvariable"
defined? @var #=> "instance-variable"

# Variablen, die mit @@ beginnen, sind für die Klasse gültig.
@@var = "Ich bin eine Klassenvariable"
defined? @@var #=> "class variable"

# Variablen, die mit einem Großbuchstaben beginnen, sind Konstanten
Var = "Ich bin eine Konstante"
defined? Var #=> "constant"

# Class ist in Ruby auch ein Objekt. Deshalb kann eine Klasse Instanzvariablen
# haben. Eine Klassenvariable wird zwischen der Klasse und all ihren 
# Ableitungen geteilt.

# Basis Klasse
class Human
  @@foo = 0

  def self.foo
    @@foo
  end

  def self.foo=(value)
    @@foo = value
  end
end

# Abgeleitete Klasse
class Worker < Human
end

Human.foo #=> 0
Worker.foo #=> 0

Human.foo = 2
Worker.foo #=> 2

# Ableitungen einer Klasse haben keinen Zugriff auf eine Eine Klassen-Instanzvariable.
class Human
  @bar = 0

  def self.bar
    @bar
  end

  def self.bar=(value)
    @bar = value
  end
end

class Doctor < Human
end

Human.bar #=> 0
Doctor.bar #=> nil

module ModuleExample
  def foo
    'foo'
  end
end

# Ein Einbinden (include) eines Moduls bindet seine Methoden an die Instanzen 
# der Klasse.
# Ein Erweitern (extend) eines Moduls bindet seine Methoden an die Klasse 
# selbst.
class Person
  include ModuleExample
end

class Book
  extend ModuleExample
end

Person.foo     #=> NoMethodError: undefined method `foo' for Person:Class
Person.new.foo #=> "foo"
Book.foo       #=> "foo"
Book.new.foo   #=> NoMethodError: undefined method `foo'


# Callbacks werden ausgeführt, wenn ein Modul eingebunden oder erweitert wird.
module ConcernExample
  def self.included(base)
    base.extend(ClassMethods)
    base.send(:include, InstanceMethods)
  end

  module ClassMethods
    def bar
      'bar'
    end
  end

  module InstanceMethods
    def qux
      'qux'
    end
  end
end

class Something
  include ConcernExample
end

Something.bar     #=> "bar"
Something.qux     #=> NoMethodError: undefined method `qux'
Something.new.bar #=> NoMethodError: undefined method `bar'
Something.new.qux #=> "qux"
```

## Weitere Links

_(z.T. auf Englisch)_

- [Offizielle Ruby Website](https://www.ruby-lang.org/de/)
- [Learn Ruby by Example with Challenges](http://www.learneroo.com/modules/61/nodes/338) - Eine Variante dieses Dokuments mit in-Browser Challenges.
- [RubyMonk](https://rubymonk.com/) - Lerne Ruby mit einer Reihe interaktiver Tutorials.
- [Offizielle Dokumentation](http://ruby-doc.org/core)
- [Ruby from other languages](https://www.ruby-lang.org/en/documentation/ruby-from-other-languages/)
- [Programming Ruby](http://www.amazon.com/Programming-Ruby-1-9-2-0-Programmers/dp/1937785491/) - Eine ältere [freie Ausgabe](http://ruby-doc.com/docs/ProgrammingRuby/) ist online verfügbar.
- [Ruby Style Guide](https://github.com/bbatsov/ruby-style-guide) - Ein von der Community erstellter Ruby coding style guide.
- [Try Ruby](http://tryruby.org) - Lerne die Grundlagen der Ruby Programmiersprache, interaktiv im Browser.