Die Programmiersprache Ruby

Blog| Forum| Wiki  

Die Artikel RubyWiki:FAQ und Tricks überschneiden sich inhaltlich. Bitte hilf mit, das zu verbessern, indem du die Artikel unter einem Namen zusammenführst.
Bitte entferne anschließend den Redundanz-Baustein.

Inhaltsverzeichnis

InPlace Array.each

Man stelle sich vor, in einem Array sind eine Reihe von Strings, denen alle die ersten beiden Buchstaben weggeschnitten werden sollen. Dafür braucht man kein neues Ziel-Array zu erzeugen sondern kann das InPlace machen. Der Trick ist, String#replace zu verwenden.

1
2
3
4
5
a = [ "xxEins", "xxZwei", "xxDrei" ]
a.each do |s|
  s.replace( s[2..-1] )
end
p a  # >> ["Eins", "Zwei", "Drei"]

Würde man es mit "s = s[2..-1]" versuchen, so weist man s ein neues String-Objekt zu. Was man aber will: Das Objekt verändern, worauf s gerade zeigt. Denn das ist genau das Objekt, worauf auch im Array referenziert wird. Man muss dieses Objekt verändern und dafür gibt es nur recht wenige Möglichkeiten. Eine davon ist replace, eine andere ist "<<".

Andersherum muss man aufpassen, dass man nicht Elemente des Array verändert, obwohl man das gar nicht wollte. Hier ein Beispiel:

1
2
3
4
5
6
7
a = [ "Eins", "Zwei", "Drei" ]

a.each do |s|
  puts s << " ist es!"
end

p a  # Ups: >> ["Eins ist es!", "Zwei ist es!", "Drei ist es!"]

Ruby Format Strings

Jeder kennt & kann sie: String-Substitution per #{}. Oft vergessen wird aber dass auch in Ruby ein (s)printf existiert. Jedoch ist dies nicht in der Klasse String zu finden, sondern im Kernel-Modul. String ueberlaedt allerdings freundlicherweise den %-Operator. In Aktion sieht das ganze dann so aus:

1
2
3
4
5
'<p id="%d" class="%s">%s</p>' % [
  @node.id,
  @node.class,
  @node.value,
]

(Mit dank an murphy für den Code)

Eine komplette Referenz findet man hier: Kernel#sprintf

Library or Main Program?

Man hat ein Ruby-Programm komplettiert und will die selbst definierten Klassen und Methoden auch in einem anderen Programm nutzen. Wenn man die Datei nun einfach lädt, will man die Aufrufe für das erste Programm nicht ausführen, sondern nur die Methoden und Klassen nutzen. Um Anweisungen nur auszuführen, wenn die aktuelle Datei auch das Main Program ist, sollte man diese daher besonders "klammern":

1
2
3
4
5
# Klassendefinitionen etc.
#...
if $0 == __FILE__ #Meint: WENN das Hauptprogramm ($0) gleich der Datei ist, in dem diese Zeile steht (__FILE__), DANN starte das Programm. 
  starte_programm
end

Zweidimensionales Array -> Hash

Oft liest man die Frage "Wie kann ich ein Array in ein Hash umwandeln?" oder "Wieso gibt's kein Array#to_h?". Nunja, nicht jedes Array erfüllt die Kriterien, um verlustfrei in ein Hash umgewandelt zu werden. Wenn man sich dessen aber sicher ist, gibt es folgenden, einfachen Weg:

myhash = Hash[*myarray.flatten]


Tiefer Klon von Objektstrukturen

Wenn man einen tiefen Klon von einem Objekt erstellen möchte und sich nicht selbst durch die Struktur hangeln will, gibt es zwei Tricks:

1
2
3
4
YAML.load( myobj.to_yaml )

# f��r alle Objekte, die YAML nicht serialisiert
Marshal.load Marshal.dump( myobj )

Daten an Coding anhängen

Hat man ein Skript, das zusätzlich zu dem Programmcode Daten benötigt, so kann man diese an das Coding nach __END__ anhängen. Die Konstante DATA verhält sich dann wie eine geöffnete Datei, die die Daten nach dem END enthält.

Beispiel:

1
2
3
4
5
6
7
DATA.each{|content|
  puts content
}
__END__
Dateninhalt 1
Dateninhalt 2
Dateninhalt 3

Wenn man DATA allerdings auf die Position 0 setzt, ist die Cursorpos am Anfang des Programms:

1
2
3
4
DATA.rewind
DATA.each{|content|
  puts content
}

Zahlen mit bestimmter Anzahl Nachkommastellen oder Nullen davor anzeigen

Weder String noch Integer bieten eine direkte Möglichkeiten Zahlen auf diese Art und Weise darzustellen. Man kann das aber über Kernel#sprintf, also über Format-Strings lösen.

1
2
3
4
#So kann man eine Zahl immer zweistellig (vor Komma) darstellen (7 durch beliegige ersetzen): 
zahl = sprintf "%02i", 7 #=> 07
#Und so auf zwei Stellen gerundet nach dem Komma: 
zahl = sprintf("%.2f", 0.1234) #=> 0.12

Externe Programme starten

Ruby bietet mehrere Möglichkeiten, andere Programme zu starten, auch wenn diese nicht in Ruby geschrieben sind. Folgendes ist möglich:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#Bindet eine Rubydatei ein, indem sie ausgef��hrt wird. Jede Datei kann nur einmal geladen werden. 
#Zum Einbinden von Definitionen gedacht. 
require "meine_lib"
#F��hrt die angegebene Ruby-Datei aus. Im Gegensatz zu "require" kann es mehrfach die gleiche Datei ausf��hren. 
load "mein_programm"
#F��hrt einen Kommandozeilenbefehl aus, der nat��rlich auch ein Programm starten kann. 
#Es wird gewartet, bis das Programm beendet ist, dann wird je nach 
#Erfolg des Aufrufs true oder false zur��ckgegeben. 
system("befehl")
#Das selbe wie oben, nur ohne warten auf das Prozessende. Gibt die PID des Prozesses zur��ck. 
spawn("befehl")
#Unter Windows kann spawn auch mithilfe der Windows-Shell erreicht werden: 
require "win32ole"
windows_shell = WIN32OLE.new("WScript.Shell")
windows_shell.Run("befehl") #(gibt ��brigens sofort 0 zur��ck)
#F��hrt einen Kommandozeilenbefehl aus, wartet, bis er zu Ende ist, und gibt seinen Output zur��ck. 
#Die Methode ` kann aber ��berschrieben werden. 
`befehl`
#Ersetzt das aktuelle Ruby-Programm an Ort und Stelle mit einem anderen. 
exec("mein_programm")


Siehe auch