Ruby

Η Ruby είναι μια δυναμική, ανακλαστική, αντικειμενοστρεφής γλώσσα προγραμματισμού γενικής χρήσης, που συνδυάζει μια σύνταξη επηρεασμένη από την Perl με χαρακτηριστικά από τη Smalltalk. Η Ruby προήλθε από την Ιαπωνία στα μέσα της δεκαετίας του 1990 και αρχικά σχεδιάστηκε και αναπτύχθηκε από τον Yukihiro "Matz" Matsumoto. Βασικές της επιρροές είναι η Perl, η Smalltalk, η Eiffel και η Lisp.
Η Ruby υποστηρίζει πολλαπλά παραδείγματα προγραμματισμού όπως ο συναρτησιακός προγραμματισμός, ο αντικειμενοστρεφής προγραμματισμός, ο προστακτικός προγραμματισμός και ο ανακλαστικός (reflective) προγραμματισμός. Έχει σύστημα δυναμικών τύπων και αυτόματη διαχείριση μνήμης, επομένως μοιάζει σε κάποια χαρακτηριστικά της με την Python, την Perl, τη Lisp, τη Dylan, την Pike και τη CLU.
Η πρότυπη υλοποίηση 1.8.7 της Ruby είναι γραμμένη σε C, σαν μια διερμηνευόμενη γλώσσα ενός περάσματος. Προς το παρόν δεν υπάρχει κάποιο επίσημο πρότυπο αναφοράς για τη γλώσσα Ruby, επομένως η αρχική υλοποίηση θεωρείται το ντε φάκτο σημείο αναφοράς. Υπάρχουν αρκετές (ολοκληρωμένες ή σε ανάπτυξη) εναλλακτικές υλοποιήσεις της γλώσσας, συμπεριλαμβανομένων των YARV, JRuby, Rubinius, IronRuby, MacRuby και HotRuby, κάθε μια από τις οποίες και έχει διαφορετική προσέγγιση, με τις IronRuby, JRuby και MacRuby να προσφέρουν just-in-time compilation και τη MacRuby να προσφέρει επιπλέον ahead-of-time compilation. Ο κώδικας της επίσημης έκδοσης 1.9 χρησιμοποιεί τη YARV, όπως και αυτός της έκδοσης 2.0 (σε ανάπτυξη), η οποία και θα αντικαταστήσει την πιο αργή Ruby MRI.

Ιστορία

Η αρχική ιδέα για τη Ruby προέκυψε στις 24 Φεβρουαρίου 1993 από το Yukihiro Matsumoto που είχε σκοπό να δημιουργήσει μια νέα γλώσσα που θα ισορροπούσε μεταξύ συναρτησιακού και προστακτικού προγραμματισμού. Ο Matsumoto έχει δηλώσει: "Ήθελα μια γλώσσα σεναρίων πιο ισχυρή από την Perl και πιο αντικειμενοστρεφή από την Python. Για αυτό αποφάσισα να σχεδιάσω τη δική μου γλώσσα".

Ετυμολογία του ονόματος "Ruby"

Το όνομα "Ruby" αποφασίστηκε στη διάρκεια μιας ηλεκτρονικής συνομιλίας μεταξύ του Matsumoto και του Keiju Ishitsuka στις 24 Φεβρουαρίου του 1993, πριν γραφεί κώδικας για τη γλώσσα. Αρχικά προτάθηκαν δύο ονόματα: "Coral" και "Ruby", με το τελευταίο να είναι η επιλογή του Matsumoto σε ένα μήνυμα ηλεκτρονικής αλληλογραφίας στη συνέχεια στον Ishitsuka. Ο Matsumoto αργότερα είχε δηλώσει ότι ένας παράγοντας υπέρ της επιλογής του ονόματος "Ruby" ήταν το ότι βρισκόταν στην "πέτρα γενεθλίων" (birthstone) ενός από τους συναδέλφους του.

Αρχική δημοσιοποίηση

Η πρώτη δημόσια έκδοση της Ruby 0.95 ανακοινώθηκε σε εγχώριες ομάδες νέων (newsgroups) της Ιαπωνίας την 21η Δεκεμβρίου 1995. Στη συνέχεια τρεις εκδόσεις της Ruby έγιναν διαθέσιμες στο διάστημα δύο ημερών, ταυτόχρονα με τη δημιουργία της λίστας ηλεκτρονικού ταχυδρομείου ruby-list (στην Ιαπωνική γλώσσα), η οποία ήταν η πρώτη λίστα για τη νέα γλώσσα.
Ήδη σε αυτή τη φάση της ανάπτυξης ήταν παρόντα αρκετά από τα χαρακτηριστικά που έγιναν γνώριμα από τις επόμενες εκδόσεις της Ruby, όπως η αντικειμενοστρεφής σχεδίαση, οι κλάσεις με κληρονομικότητα, τα mixin, οι απαριθμητές (iterators), τα κλεισίματα (closures), ο χειρισμός εξαιρέσεων (exception handling), και η συλλογή απορριμμάτων.

Ruby 1.0

Η Ruby έφτασε την έκδοση 1.0 στις 25 Δεκεμβρίου 1996.
Μετά την έκδοση Ruby 1.3 το 1999, άρχισε η πρώτη λίστα ταχυδρομείου στην αγγλική γλώσσα, η ruby-talk, που υπήρξε η αρχή ενός αυξανόμενου ενδιαφέροντος για τη γλώσσα εκτός Ιαπωνίας. Το Σεπτέμβριο του 2000, τυπώθηκε το πρώτο βιβλίο στην αγγλική, το "Programming Ruby", το οποίο και αργότερα δημοσιεύθηκε ελεύθερα για το κοινό, ωθώντας και άλλο τη χρήση της Ruby στον αγγλόφωνο κόσμο.

Φιλοσοφία

Ο Matsumoto έχει πει ότι η Ruby έχει σχεδιαστεί για παραγωγικότητα και ευχάριστη χρήση από τον προγραμματιστή, ακολουθώντας τις αρχές της καλής σχεδίασης διεπαφών χρήστη. Τονίζει ότι η σχεδίαση συστημάτων πρέπει να δίνει έμφαση στις ανθρώπινες ανάγκες, και όχι σε αυτές του υπολογιστή:
Συχνά οι άνθρωποι, ειδικά οι μηχανικοί υπολογιστών, εστιάζουν στους υπολογιστές. Σκέφτονται: "Κάνοντας αυτό, ο υπολογιστής θα τρέξει πιο γρήγορα. Κάνοντας αυτό, ο υπολογιστής θα τρέξει πιο αποδοτικά. Κάνοντας αυτό, ο υπολογιστής θα ..." Εστιάζουν την προσοχή τους στους υπολογιστές. Αλλά στην πραγματικότητα πρέπει να εστιάσουμε στους ανθρώπους, στο πώς οι άνθρωποι προγραμματίζουν ή χειρίζονται τις εφαρμογές των υπολογιστών. Είμαστε τα αφεντικά. Οχι οι σκλάβοι.
Η Ruby λέγεται ότι ακολουθεί την "αρχή της ελάχιστης έκπληξης", το οποίο σημαίνει ότι η γλώσσα πρέπει να συμπεριφέρεται έτσι ώστε να μην μπερδεύονται οι έμπειροι χρήστες της. Ο Matsumoto έχει πει ότι ο βασικός στόχος της σχεδίασής του ήταν να δημιουργήσει μια γλώσσα, την οποία θα απολάμβανε ο ίδιος να χρησιμοποιεί, ελαχιστοποιώντας την προγραμματιστική δουλειά και τα πιθανά διφορούμενα σημεία. Έχει πει ότι δεν είχε εφαρμόσει την αρχή της ελάχιστης έκπληξης στη Ruby, αλλά η φράση έχει πια συνδεθεί στενά με αυτήν. Η φράση η ίδια έχει υπάρξει πηγή εκπλήξεων, αφού οι αρχάριοι χρήστες πιστεύουν ότι σημαίνει ότι οι συμπεριφορές της Ruby προσπαθούν να μοιάσουν σε αυτές άλλων γνώριμων γλωσσών. Σε μια συζήτηση το Μάιο του 2005 στην ομάδα comp.lang.ruby, ο Matsumoto προσπάθησε να κρατήσει μια απόσταση μεταξύ της Ruby και της παραπάνω "αρχής", εξηγώντας ότι, αφού κάθε σχεδιαστική απόφαση θα καταπλήξει κάποιον, χρησιμοποιεί ένα προσωπικό μέτρο για την αποτίμηση της "έκπληξης". Αν αυτό το προσωπικό μέτρο παραμένει συνεπές, θα υπάρχουν λίγες εκπλήξεις για αυτούς που το γνωρίζουν.
Ο Matsumoto το περιέγραψε ως εξής σε μια συνέντευξη:
Κάθε άνθρωπος έχει ένα προσωπικό παρελθόν. Κάποιος μπορεί να ήρθε από την Python, κάποιος άλλος από την Perl, και μπορεί να εκπλαγούν από διάφορες όψεις της γλώσσας. Τότε έρχονται και μου λένε, 'ένιωσα έκπληξη από αυτό το χαρακτηριστικό της γλώσσας, η Ruby παραβαίνει την αρχή της ελάχιστης έκπληξης.' Περίμενε. Περίμενε. Η αρχή της ελάχιστης έκπληξης δεν είναι μόνο για εσένα. Η αρχή της ελάχιστης έκπληξης σημαίνει την αρχή της ελάχιστης δικής μου έκπληξης. Και αυτό σημαίνει ότι ισχύει όταν έχεις μάθει τη Ruby αρκετά καλά. Για παράδειγμα, ήμουν προγραμματιστής της C++ πριν αρχίσω τη σχεδίαση της Ruby. Προγραμμάτιζα αποκλειστικά σε C++ για δύο με τρία χρόνια. Και μετά από δύο χρόνια προγραμματισμού με C++, η γλώσσα αυτή εξακολουθεί να με εκπλήσσει.

Σημασιολογία

Η Ruby είναι αντικειμενοστρεφής: κάθε τύπος δεδομένων είναι αντικείμενο, συμπεριλαμβανομένων και των κλάσεων και των τύπων που άλλες γλώσσες θεωρούν βασικούς (όπως οι ακέραιοι, οι τιμές αλήθειας και η τιμή "nil"). Κάθε συνάρτηση είναι μια μέθοδος. Οι τιμές με όνομα (μεταβλητές) πάντα είναι αναφορές σε αντικείμενα, και όχι τα ίδια τα αντικείμενα. Η Ruby υποστηρίζει κληρονομικότητα με δυναμική διανομή μεθόδων (dynamic dispatch),  mixin και μεθόδους singleton (που ανήκουν και ορίζονται μόνο σε ένα αντικείμενο και όχι σε ολόκληρη την κλάση). Αν και η Ruby δεν υποστηρίζει πολλαπλή κληρονομικότητα, οι κλάσεις μπορούν να εισάγουν μονάδες κώδικα (modules) σαν mixin. Η διαδικαστική σύνταξη υποστηρίζεται αλλά όλες οι μέθοδοι που ορίζονται εκτός της εμβέλειας ενός συγκεκριμένου αντικειμένου είναι στην πραγματικότητα μέθοδοι της κλάσης Object. Επειδή η κλάση αυτή είναι η βασική κλάση κάθε άλλης βάσης, οι αλλαγές είναι ορατές σε όλες τις κλάσεις και τα αντικείμενα.
Η Ruby έχει περιγραφεί σαν γλώσσα προγραμματισμού πολλών παραδειγμάτων: επιτρέπει διαδικαστικό προγραμματισμό (ο ορισμός συναρτήσεων/μεταβλητών εκτός κλάσεων τις κάνει μέρος της κλάσης ρίζας, 'self' Object), με αντικειμενοστρεφή χαρακτηριστικά (τα πάντα είναι αντικείμενα) ή συναρτησιακά χαρακτηριστικά και συνέχειες - όλες οι εντολές έχουν τιμές, και οι συναρτήσεις επιστρέφουν την τελευταία τιμή τους). Επιτρέπει ενδοσκόπηση (introspection), ανάκλαση (reflection) και μεταπρογραμματισμό, και υποστηρίζει  νήματα βασισμένα στο διερμηνέα. Η Ruby έχει δυναμικό σύστημα τύπων και υποστηρίζει παραμετρικό πολυμορφισμό.
Σύμφωνα με τη λίστα συχνών ερωτήσεων της Ruby,:
"Αν σας αρέσει η Perl, θα σας αρέσει η Ruby και θα νιώσετε άνετα με τη σύνταξή της. Αν σας αρέσει η Smalltalk, θα σας αρέσει η Ruby και θα νιώσετε άνετα με τη σημασιολογία της. Αν σας αρέσει η Python, μπορεί (ή μπορεί και όχι) να σας ξενίσει η τεράστια διαφορά στη φιλοσοφία σχεδίασης μεταξύ της Python και των Ruby/Perl."

Σύνταξη

Η σύνταξη της Ruby είναι παρόμοια με αυτή της Perl και της Python. Οι ορισμοί κλάσεων και μεθόδων ξεχωρίζουν από λέξεις-κλειδιά. Σε αντίθεση με την Perl, δεν είναι απαραίτητο οι μεταβλητές να έχουν στην αρχή τους ένα αναγνωριστικό σύμβολο. Όταν αυτό όμως χρησιμοποιείται αλλάζει η σημασία της εμβέλειας της μεταβλητής. Η εμφανέστερη διαφορά σε σχέση με τη C και την Perl είναι ότι συνήθως χρησιμοποιούνται λέξεις-κλειδιά για τον ορισμό λογικών ενοτήτων κώδικα, χωρίς αγκύλες (δηλ., ζευγάρι { και }). Για πρακτικούς λόγους, δεν υπάρχει διαχωρισμός μεταξύ εκφράσεων και εντολών. Οι αλλαγές γραμμής είναι σημαντικές και αποτελούν το τέλος μιας εντολής - επίσης μπορεί να χρησιμοποιηθεί ένα ελληνικό ερωτηματικό στη θέση τους. Σε αντιδιαστολή με την Python, οι εσοχές (indentation) δεν έχουν σημασία.
Μια από τις διαφορές της Ruby σε σχέση με την Python και την Perl είναι ότι η Ruby κρατά όλες τις μεταβλητές ενός αντικειμένου σαν ιδιωτικές (private) μέσα σε μια κλάση και τις εκθέτει προς τα έξω μόνο μέσω μεθόδων πρόσβασης (attr_writer, attr_reader, κλπ.). Σε αντίθεση με τις μεθόδους "getter" και "setter" άλλων γλωσσών όπως η C++ ή η Java, οι μέθοδοι πρόσβασης στη Ruby δημιουργούνται με μια γραμμή κώδικα με χρήση μεταπρογραμματισμού. Επειδή η κλήση αυτών των μεθόδων δε χρειάζεται παρενθέσεις, είναι εύκολο να αλλάξουμε μια μεταβλητή ενός αντικειμένου σε μια πλήρη συνάρτηση, χωρίς να αλλάξουμε ούτε μια γραμμή κώδικα ή refactoring, επιτυγχάνοντας παρόμοια λειτουργικότητα με τα μέλη ιδιοτήτων της C# και της VB.NET. Οι περιγραφείς ιδιοτήτων της Python (property descriptors) είναι παρόμοιοι αλλά έχουν ένα κόστος στη φάση της ανάπτυξης του λογισμικού. Αν κάποιος αρχίσει στην Python με μια δημόσια μεταβλητή ενός αντικειμένου και στη συνέχεια αλλάξει την υλοποίησή της σε μια ιδιωτική μεταβλητή που φαίνεται μέσα από έναν περιγραφέα ιδιοτήτων, ο εσωτερικός κώδικας της κλάσης μπορεί να χρειαστεί να διορθωθεί ώστε να χρησιμοποιεί την ιδιωτική μεταβλητή και όχι τη δημόσια. Η Ruby αφαιρεί αυτήν την επιλογή της σχεδίασης, επιβάλλοντας όλες οι μεταβλητές αντικειμένων να είναι ιδιωτικές, αλλά παρέχει έναν απλό τρόπο να ορίζονται μέθοδοι get και set. Αυτό συμφωνεί με την ιδέα ότι στη Ruby, κανείς δεν έχει άμεση πρόσβαση στα εσωτερικά μέλη μιας κλάσης από το εξωτερικό της αλλά μπορεί μόνο να στείλει ένα μήνυμα στην κλάση και να λάβει μια απάντηση.
Δείτε τα παραδείγματα για δείγματα κώδικα που δείχνουν τη σύνταξη της Ruby.

Παραδείγματα

Τα παρακάτω παραδείγματα μπορούν να εκτελεστούν από ένα κέλυφος της Ruby όπως το Interactive Ruby Shell ή να αποθηκευτούν σε ένα αρχείο και να εκτελεστούν από τη γραμμή εντολών γράφοντας ruby <filename>.
Το κλασικό παράδειγμα Hello world:
puts "Hello World!"
Βασικός κώδικας σε Ruby:
# Τα πάντα, συμπεριλαμβανομένων των τιμών, είναι αντικείμενα, επομένως αυτό δουλεύει:-199.abs                                                # 199"ruby is cool".length                                   # 12"Your mother is nice.".index("u")                       # 2"Nice Day Isn't It?".downcase.split("").uniq.sort.join  # " '?acdeinsty"
Μετατροπές:
puts "What's your favorite number?"number = gets.chompoutput_number = number.to_i + 1puts output_number.to_s + ' is a bigger and better favorite number.'

Συμβολοσειρές

Υπάρχουν διάφοροι τρόποι να δηλωθούν συμβολοσειρές στη Ruby.
Τα παρακάτω παραδείγματα είναι ισοδύναμα και υποστηρίζουν την παρεμβολή συμβολοσειρών (interpolation):
a = "\nThis is a double-quoted string\n"a = %Q{\nThis is a double-quoted string\n}a = %{\nThis is a double-quoted string\n}a = %/\nThis is a double-quoted string\n/a = <<-BLOCKThis is a double-quoted stringBLOCK
Οι παρακάτω αναθέσεις είναι ισοδύναμες και παράγουν βασικές συμβολοσειρές:
a = 'This is a single-quoted string'a = %q{This is a single-quoted string}

Συλλογές

Δημιουργία και χρήση ενός πίνακα:
a = [1, 'hi', 3.14, 1, 2, [4, 5]]
 
puts a[2]           # 3.14puts a.[](2)        # 3.14puts a.reverse      # [[4, 5], 2, 1, 3.14, 'hi', 1]puts a.flatten.uniq # [1, 'hi', 3.14, 2, 4, 5]
Δημιουργία και χρήση ενός πίνακα συσχετίσεων (πίνακες κατακερματισμού ή hashes στη Ruby):
hash = { :water => 'wet', :fire => 'hot' }puts hash[:fire] # Τυπώνει:  hothash.each_pair do |key, value| # Ή:  hash.each do |key, value|
  puts "#{key} is #{value}"end
 
# Τυπώνει: water is wet#          fire is hothash.delete :water # Σβήνει το :water => 'wet'hash.delete_if {|key,value| value=='hot'} # Σβήνει το :fire => 'hot'

Ενότητες και απαριθμητές

Σύνταξη με δύο τρόπους για τη δημιουργία ενοτήτων κώδικα:
{ puts "Hello, World!" } # Παρατηρήστε τις { αγκύλες }#ήdo puts "Hello, World!" end
Όταν δημιουργείται μια ενότητα κώδικα, πάντα είναι συνδεδεμένη με μια μέθοδο, ως προαιρετική παράμετρο της ενότητας.
Πέρασμα σαν παράμετρο μιας ενότητας για να είναι κλείσιμο:
# Σε μια μεταβλητή αντικειμένου (σημειώνεται με '@') καταγράφεται η ενότητα.def remember(&a_block)
  @block = a_blockend
 
# Κλήση της παραπάνω μεθόδου, της δίνεται μια ενότητα που παίρνει ένα όνομα.remember {|name| puts "Hello, #{name}!"}
 
# Όταν πρέπει (για το αντικείμενο) -- κάλεσε το κλείσιμο!@block.call("Jon")# => "Hello, Jon!"
Δημιουργία μιας ανώνυμης συνάρτησης:
proc {|arg| print arg}Proc.new {|arg| print arg}lambda {|arg| print arg}
Επιστροφή ενός κλεισίματος από μια μέθοδο:
def create_set_and_get(initial_value=0) # Εξ'ορισμού τιμή  0
  closure_value = initial_value
  return Proc.new {|x| closure_value = x}, Proc.new { closure_value }endsetter, getter = create_set_and_get  # δηλ. επιστρέφει δυο τιμέςsetter.call(21)getter.call # => 21#Μπορείτε επίσης να χρησιμοποιήσετε μια μεταβλητή παράμετρο σαν δέσμευση για το κλείσιμο. #Το παραπάνω μπορεί να γραφεί σαν...def create_set_and_get(closure_value=0)
  proc {|x| closure_value = x } , proc { closure_value }end
Αποδίδοντας τη ροής του ελέγχου προγράμματος σε μια ενότητα που δόθηκε στο χρόνο κλήσης:
def use_hello
  yield "hello"end
 
# Κλήση της παραπάνω μεθόδου, δίνοντάς της μια ενότητα.use_hello {|string| puts string} # => 'hello'
Απαρίθμηση ακολουθιών και πινάκων με τη χρήση ενοτήτων:
array = [1, 'hi', 3.14]array.each {|item| puts item }# => 1# => 'hi'# => 3.14array.each_index {|index| puts "#{index}: #{array[index]}" }# => 0: 1# => 1: 'hi'# => 2: 3.14(3..6).each {|num| puts num }# => 3# => 4# => 5# => 6
Μια μέθοδος όπως η inject() μπορεί να δέχεται και μια παράμετρο και μια ενότητα. Η inject εκτελείται σε κάθε μέλος μιας λίστας, εκτελώντας κάποια συνάρτηση σε αυτό, κρατώντας ένα σύνολο. Αυτό είναι ανάλογο με τη συνάρτηση foldl στις συναρτησιακές γλώσσες προγραμματισμού. Για παράδειγμα:
[1,3,5].inject(10) {|sum, element| sum + element} # => 19
Στο πρώτο πέρασμα, η ενότητα δέχεται το 10 (την παράμετρο) σαν sum, και το 1 (το πρώτο στοιχείο του πίνακα) σαν στοιχείο και επιστρέφει 11. Το 11 τότε γίνεται το sum του επόμενου περάσματος, που προστίθεται στο 3 για να γίνει 14. Το 14 στη συνέχεια προστίθεται στο 5, για να επιστρέψει τελικά 19.
Οι ενότητες δουλεύουν με πολλές ενσωματωμένες μεθόδους:
File.open('file.txt', 'w') do |file| # 'w' σημαίνει "γράψιμο".
  file.puts 'Wrote some text.'end                                  # Το αρχείο κλείνει αυτόματα εδώFile.readlines('file.txt').each do |line|
  puts lineend# => Wrote some text.
Χρησιμοποιώντας μια απαρίθμηση και μια ενότητα για να πάρουμε το τετράγωνο των αριθμών από το 1 ως το 10:
(1..10).collect {|x| x*x} # => [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

Κλάσεις

Ο παρακάτω κώδικας ορίζει μια κλάση με το όνομα Person. Εκτός του 'initialize', του κλασικού κατασκευαστή (constructor) που δημιουργεί νέα αντικείμενα, έχει δύο μεθόδους: μία που αντικαθιστά τον τελεστή σύγκρισης <=> (ώστε το Array#sort να ταξινομεί κατά ηλικία) και μία που αντικαθιστά τη μέθοδο to_s (ώστε η Kernel#puts να μπορεί να μορφοποιήσει την έξοδό της). Εδώ ο κώδικας "attr_reader" είναι ένα παράδειγμα μεταπρογραμματισμού σε Ruby: η "attr_accessor" ορίζει μεθόδους "getter" και "setter" των μεθόδων των αντικειμένων, ενώ η "attr_reader" μόνο μεθόδους "getter". Επίσης, η τελευταία αποτιμημένη εντολή μιας μεθόδου είναι και η τιμή που επιστρέφει, επιτρέποντας την παράλειψη της 'return'.
class Person
  attr_reader :name, :age
  def initialize(name, age)
    @name, @age = name, age
  end
  def <=>(person) # Τελεστής σύγκρισης για ταξινόμηση
    @age <=> person.age
  end
  def to_s
    "#@name (#@age)"
  endend
 
group = [
  Person.new("Bob", 33), 
  Person.new("Chris", 16), 
  Person.new("Ash", 23) 
]puts group.sort.reverse
Τα παραπάνω τυπώνουν τρία ονόματα σε αντίστροφη σειρά ηλικίας:
Bob (33)
Ash (23)
Chris (16)

Ανοιχτές κλάσεις

Στη Ruby οι κλάσεις δεν είναι ποτέ κλειστές: μπορείτε πάντα να προσθέσετε μεθόδους σε μια υπάρχουσα κλάση. Αυτό εφαρμόζεται τόσο στις κλάσεις που γράφετε, όσο και στις ενσωματωμένες κλάσεις. Το μόνο που έχετε να κάνετε είναι να ανοίξετε τον ορισμό μιας υπάρχουσας κλάσης, και τα νέα περιεχόμενα που θα ορίσετε θα προστεθούν εκεί. Ένα απλό παράδειγμα πρόσθεσης μια νέας μεθόδου στην κλάση Time της βασικής βιβλιοθήκης:
# ξανα-ανοίγει την κλάση Time της Rubyclass Time
  def yesterday
    self - 86400
  endend
 
today = Time.now # => Thu Aug 14 16:51:50 +1200 2008yesterday = today.yesterday # => Wed Aug 13 16:51:50 +1200 2008
Η προσθήκη μεθόδων σε κλάσεις που έχουν ήδη οριστεί συχνά ονομάζεται "μπάλωμα-μαϊμού" (monkey-patching). Η πρακτική αυτή, μπορεί να οδηγήσει σε πιθανές συγκρούσεις όσον αφορά τη συμπεριφορά του κώδικα και στη συνέχεια σε απρόβλεπτα αποτελέσματα. Αν ακολουθείται χωρίς προσοχή μπορεί να οδηγήσει σε πρόβλημα διαχείρισης του μεγέθους του κώδικα.

Εξαιρέσεις

Μια εξαίρεση εμφαίζεται με την κλήση της raise:
raise
Σε μια εξαίρεση μπορεί να προστεθεί ένα προαιρετικό μήνυμα:
raise "This is a message"
Μπορεί επίσης να δοθεί ο τύπος της εξαίρεσης:
raise ArgumentError, "Illegal arguments!"
Εναλλακτικά μπορείτε να περάσετε ένα στιγμιότυπο μιας εξαίρεσης στη μέθοδο raise:
raise ArgumentError.new("Illegal arguments!")
Το παρακάτω σχήμα κώδικα είναι χρήσιμο όταν θέλετε να εμφανιστεί μια εξαίρεση κάποιας ιδιαίτερης κλάσης, της οποίας ο κατασκευαστής δέχεται παραπάνω από ένα ορίσματα:
class ParseError < Exception
  def initialize input, line, pos
    super "Could not parse '#{input}' at line #{line}, position #{pos}"
  endendraise ParseError.new("Foo", 3, 9)
Οι εξαιρέσεις χειρίζονται από την πρόταση rescue. Μια τέτοια πρόταση μπορεί να πιάσει τις εξαιρέσεις που κληρονομούν από την StandardError. Επίσης οι else και ensure υποστηρίζουν τη χρήση με εξαιρέσεις.
begin# Κάνε κάτιrescue# Χειρισμός της εξαίρεσηςelse# Αλλιώς κάνε αυτό αν δεν εμφανίστηκε εξαίρεσηensure# Κάνε αυτό σε κάθε περίπτωση (είτε εμφανίστηκε εξαίρεση ή όχι)end
Ένα κοινό λάθος είναι να προσπαθείτε να πιάσετε όλες τις εξαιρέσεις με μια μόνο πρόταση rescue. Αυτό γίνεται σωστά ως εξής:
begin# Κάνε κάτιrescue Exception # όχι απλά rescue -- αυτό πιάνει μόνο την StandardError, υποκλάση της Exception# Χειρισμός της εξαίρεσηςend
Ο χειρισμός συγκεκριμένων εξαιρέσεων γίνεται ως εξής:
begin# ...rescue RuntimeError 
# χειρισμόςend
Επίσης το αντικείμενο της εξαίρεσης μπορεί να γίνει διαθέσιμο στο σώμα κώδικα του χειριστή της εξαίρεσης:
begin# ...rescue RuntimeError => e# χειριστής που μπορεί να χρησιμοποιεί το e, όπως η "print e.to_s"end
Εναλλακτικά η πιο πρόσφατη εξαίρεση αποθηκεύεται στη "μαγική" καθολική μεταβλητή $!.
Μπορείτε επίσης να πιάσετε πολλές εξαιρέσεις:
begin# ...rescue RuntimeError, Timeout::Error => e# χειριστής που μπορεί να χρησιμοποιεί το eend

Υλοποιήσεις

Η έκδοση 1.9 της Ruby, αποτελείται από μια μοναδική υλοποίηση γραμμένη σε C που χρησιμοποιεί μια εικονική μηχανή ειδική για Ruby.
Η έκδοση 1.8 της Ruby έχει δυο βασικές υλοποιήσεις: τον επίσημο διερμηνέα της Ruby, ο οποίος συχνά αποκαλείται και "Ο διερμηνέας του Matz για τη Ruby" ή MRI, και είναι αυτός που χρησιμοποιείται πιο συχνά, και τη JRuby, μια υλοποίηση βασισμένη σε Java που εκτελείται στην εικονική μηχανή της Java.
Υπάρχουν και άλλες λιγότερο γνωστές ή νεότερες υλοποιήσεις όπως η Cardinal (υλοποιημένη στην εικονική μηχανή Parrot), η IronRuby, η MacRuby, η MagLev, η Rubinius, η Ruby.NET, η XRuby και η HotRuby (εκτελεί κώδικα Ruby σε φυλλομετρητές ιστού και στην πλατφόρμα Flash).
Το πόσο ώριμη είναι μια υλοποίηση της Ruby συνήθως μετράται από το αν είναι ικανή να εκτελεί το πλαίσιο Ruby on Rails (Rails), γιατί είναι πολύπλοκο στην υλοποίηση και χρησιμοποιεί πολλά χαρακτηριστικά που είναι μόνο διαθέσιμα στη Ruby. Το σημείο στο οποίο μια υλοποίηση μπορεί να το πετύχει αυτό, ονομάζεται η μοναδικότητα των Rails (The Rails singularity). Μέχρι το Μάιο του 2010, μόνο η βασική υλοποίηση (MRI) και η JRuby μπορούν να εκτελέσουν το Rails χωρίς τροποποιήσεις σε ένα περιβάλλον παραγωγής. Η Rubinius κυκλοφόρησε την έκδοση 1.0 που μπορεί να εκετελεί το Rails, αλλά δεν είναι σίγουρο ότι μπορεί να χρησιμοποιηθεί σε περιβάλλοντα παραγωγής ακόμα. Η IronRuby μπορεί να τρέξει κάποιες δοκιμαστικές περιπτώσεις του Rails, αλλά ακόμα δεν είναι έτοιμη για περιβάλλοντα παραγωγής.
Η Ruby είναι διαθέσιμη σε πολλά λειτουργικά συστήματα όπως το Linux, το Mac OS X, τα Microsoft Windows, τα Windows CE και οι πιο πολλές εκδόσεις του Unix.
Η Ruby 1.9 πρόσφατα μεταφέρθηκε στο Symbian OS 9.x.

Αποθήκες κώδικα και βιβλιοθήκες

Το Ruby Application Archive (RAA) και το RubyForge, λειτουργούν σαν αποθήκες κώδικα (repositories) για πολλές εφαρμογές και βιβλιοθήκες της Ruby, περιλαμβάνοντας πάνω από 7000 αντικείμενα. Αν και ο αριθμός των εφαρμογών που είναι διαθέσιμος δεν είναι ίδιος με αυτόν των κοινοτήτων της Perl ή της Python, υπάρχουν πολλά εργαλεία που ενθαρρύνουν την περαιτέρω ανάπτυξη κώδικα στη γλώσσα.
Ο RubyGems έχει γίνει ο βασικός διαχειριστής πακέτων για βιβλιοθήκες σε Ruby. Ο σκοπός του μοιάζει με το CPAN της Perl αλλά η χρήση του μοιάζει πιο πολύ με το apt-get.
Πρόσφατα πολλές παλιές και νέες βιβλιοθήκες στεγάζονται στο GitHub, το οποίο εστιάζει στο Git και είχε βασική υποστήριξη για πακετάρισμα RubyGems.