Ganz ohne Aufsehen wurde vor einigen Tagen ein kleines Helferlein für die Ruby-Werkzeugkiste veröffentlicht: Unroller. Zweck dieser Ruby-Bibliothek ist menschenlesbare Traces der Programmausführung zu generieren – und das auch noch in bunt:
Unroller eignet sich besonders zum Analysieren von unbekannten Bibliotheken oder auch zur Fehlersuche. Installiert wird die Bibliothek einfach via gem1 (gem install unroller).
Es gibt zwei grundlegende Ansätze die Trace-Funktionalität zu nutzen: Entweder globales Tracing, unter Verwendung der Methoden Unroller.trace zum Einschalten und Unroller.trace_off zum Ausschalten der Trace-Ausgabe oder lokales Tracing, indem der Methode Unroller.trace ein Block mitgegeben wird und die Ausgabe nur für die darin aufgerufenen Methoden stattfindet. Die erste Möglichkeit ist insbesondere für längere Programmstücke geeignet, während sich letztere besonders gut zum Testen einzelner Methoden benutzen lässt, wie obiges Beispiel zeigt.
Für die Feinabstimmung der Ausgabe gibt es noch diverse Optionen, z. B. um bestimmte Klassen oder Methoden von der Ausgabe auszuschließen oder die Ausgabetiefe zu begrenzen. Weitere Infos dazu sind in der API-Doku nachzulesen.
1 Unter Windows muss außerdem win32console installiert sein.
Wie ich gerade erfahren habe, wurde gestern die Version 0.9.2 von JRuby veröffentlicht. Wer das Treiben im JRuby Trunk verfolgt wird nix besonderes finden, für alle anderen sei gesagt, dass OpenSSL und Readline jetzt kompatibel mit MRI sind. Weiterhin wurden eine Menge Fehler behoben. Ein paar Stellen wurden einem Redesign unterworfen. Es wurde am Compiler weitergebastelt und (wie sollte es auch anders sein) der Rails Support und die Geschwindigkeit wurde marginal verbessert.
Mich würde mal interessieren ob jemand JRuby praktisch verwendet. Ich hab auf Arbeit mal ein paar Tests mithilfe einer früheren JRuby Version für Javaapplikationen geschrieben. Was macht Ihr damit so?
Nippon, we have a problem.
RUBY_PATCHLEVEL.Ich möchte versuchen, Licht ins Dunkel zu bringen.
Folgende Änderungen unterscheiden Ruby 1.8.5-ps (2006-12-04) von Ruby 1.8.5 (2006-08-29):
ChangeLogMon Dec 4 10:22:26 2006 URABE Shyouhei* stable version 1.8.5-p2 relased. Sun Dec 3 17:11:12 2006 Shugo Maeda * lib/cgi.rb (CGI::QueryExtension::read_multipart): should quote boundary. JVN#84798830 Sun Nov 26 16:36:46 2006 URABE Shyouhei * version.h: addition of RUBY_PATCHLEVEL. * version.c: ditto. Sat Sep 23 21:34:15 2006 Yukihiro Matsumoto * lib/cgi.rb (CGI::QueryExtension::read_multipart): CGI content may be empty. a patch from Jamis Buck .
Jetzt sehen wir auch mal, wer die Lücke gefunden hat: Danke, Jamis!
lib/cgi.rb@@ -967,6 +967,7 @@ def read_multipart(boundary, content_length) params = Hash.new([]) boundary = "--" + boundary + quoted_boundary = Regexp.quote(boundary, "n") buf = "" bufsize = 10 * 1024 boundary_end="" @@ -998,7 +999,7 @@ end body.binmode if defined? body.binmode - until head and /#{boundary}(?:#{EOL}|--)/n.match(buf) + until head and /#{quoted_boundary}(?:#{EOL}|--)/n.match(buf) if (not head) and /#{EOL}#{EOL}/n.match(buf) buf = buf.sub(/\\\\A((?:.|\\\\n)*?#{EOL})#{EOL}/n) do @@ -1018,14 +1019,14 @@ else stdinput.read(content_length) end - if c.nil? + if c.nil? || c.empty? raise EOFError, "bad content body" end buf.concat(c) content_length -= c.size end - buf = buf.sub(/\\\\A((?:.|\\\\n)*?)(?:[\\\\r\\\\n]{1,2})?#{boundary}([\\\\r\\\\n]{1,2}|--)/n) do + buf = buf.sub(/\\\\A((?:.|\\\\n)*?)(?:[\\\\r\\\\n]{1,2})?#{quoted_boundary}([\\\\r\\\\n]{1,2}|--)/n) do body.print $1 if "--" == $2 content_length = -1
Hier stecken also die eigentlichen Fehler.
stdinput.read gab einen leeren String zurück anstatt nil, wenn das Ende des Inputs erreicht war.
Dadurch entstand eine Endlosschleife. Auslösen konnte man das einfach, indem man eine Multipart-Form an cgi.rb schickt,
die nicht mit dem erwarteten Zeichen endet.boundary wurde nicht maskiert. Wenn man boundary auf (?!) oder so etwas setzt, wird es nie gefunden.
Oder man fügt einer dieser "Milliarden Jahre Rechenzeit"-Regexps ein.Ich weiß leider nicht, wer die zweite Lücke gefunden hat.
Bleibt noch das neue Patchlevel:
version.c und version.h
const int ruby_patchlevel = RUBY_PATCHLEVEL;
...
rb_define_global_const("RUBY_PATCHLEVEL", INT2FIX(RUBY_PATCHLEVEL));
...
#define RUBY_PATCHLEVEL 2
...
RUBY_EXTERN const int ruby_patchlevel;
Die Diskussion um die Einführung des Patchlevels und eines neuen CVS-Branches (er schient jetzt ruby_1_8_5 zu heißen) findet ihr im Archiv.
Baut folgende Prüfung ein, wenn eure Skripte cgi.rb benutzen (soweit ich weiß, tun das unter anderem alle Rails-Applikationen; laut Jeremy Kemper ist Rails aber nicht betroffen, wenn man im production-Mode unter FastCGI arbeitet.)
if not defined? RUBY_PATCHLEVEL or (RUBY_VERSION <= '1.8.5' and RUBY_PATCHLEVEL < 2) raise SecurityError, 'Please use Ruby 1.8.5-p2 or later!' end
Based on how the cgi.rb file is coded it's most likely that there will be more of these kinds of defects in the future.(Zed A .Shaw, der Mongrel-Typ) [Edit: Prüfungscode für Ruby 1.9 angepasst (Patchlevel natürlich nur für bereits veröffentlichte Versionen.)]
In einer freien Minute habe ich nun BlindOptic um ein Layoutmanager bereichert. Das Ganze hab ich unter den wohlklingenden Namen YAML Stylesheets gestellt.
Wie gestern schon angekündigt, (ist|war) mein nächstes Spielziel ein GUI-Element innerhalb meiner kleinen Klasse ansprechbar zu machen. Das alles war in weniger als 15 Minuten erledigt, instance_variable_set sei dank aber dazu später mehr. Als erstes einmal ein kleiner neuer Codeschnippsel:
Ich hatte mir heute während der Fahrt von Bremen nach Hannover kurz Gedanken über einen ersten Entwurf von BlindOptic gemacht. Was entstanden ist möchte ich nun kurz zeigen und hoffe auf viel Kritik.
RubyInline sollte ja bereits mehrheitlich bekannt sein. Mit diesem kleinen Projekt war es bisher möglich, C/C++ Code direkt in Ruby zu nutzen. Dafür konnte man einfache Zeichenketten mit dem C Code erstellen und diese direkt in Ruby ausführen. Seit der neusten Version gibt es das Paket InlineFortran, mit diesem ist es nun auch möglich direkt Fortran zu nutzen. Für die Jüngeren unter uns (also auch für mich): Fortran ist eine Programmiersprache die bei weitem schöner aussieht als C und dabei sogar noch älter ist:
! iFunc() sei eine Funktion,
! die einen INTEGER Wert berechnet.
! Der Compiler muss nur einen Aufruf
! von iFunc erzeugen.
DO i= 1, iFunc(4711)
  !.. sinnvolles hier.
  ! Innerhalb dieser Schleife darf i
  ! nicht veraendert werden.
ENDDO
Die Ruby-Core Gurus scheinen heute aktiv zu sein. So wurde vor wenigen Stunden die JRuby Version 0.9.1 nach knapp drei Monaten Entwicklungszeit veröffentlicht. Wenn man die Features, Bugfixe und Erweiterungen liest, wird einem ganz schwindelig:
Ziel für die 0.9.2 ist u.a. die vollständige Implementierung von YAML in Java, eine funktionierende OpenSSL Bibliothek und wie immer die Peformance weiter zu steigern.
Wie ich soebend von John Lam erfahren habe, hat Microsoft nun mit Sun gleichgezogen. Nochmal eine kleine Wiederholung, für alle die, die in den letzten Wochen nix mitbekommen haben. Mit JRuby existierte seit nun knapp 2 Jahren ein Ruby Interpreter, der vollständig in Java geschrieben ist. Dieser konnte direkt mit dem Java Framework in Kontakt treten. Sun hielt dieses Projekt scheinbar für so fruchtbar, dass sie sich entschieden, die beiden Core Entwickler anzuheuern und nun Vollzeit an JRuby arbeiten zu lassen.
Soviel zur Vergangenheit. Und nun ein paar etwas neuere Informationen. Mit RubyCLR existiert ebenfalls seit einiger Zeit ein Layer der es ermöglicht, mithilfe von Ruby Code direkt mit dem .NET Framework in Kontakt zu treten. Und nun hört her: Microsoft hält dieses Projekt wohl für so fruchtbar, dass Sie sich dazu entschieden haben, den Hauptentwickler anzuheuern! Laut seiner Aussage ist es noch nicht 100% sicher ob er direkt an RubyCLR weiterarbeitet. Er wird jedoch im Bereich Skriptsprachen für .NET tätig sein... WOW
Es war einmal vor langer Zeit..
..ein kleines Mädchen. Dieses Mädel, mit dem liebreizenden Namen Tina Teenager, war voller Lebensglück und heiteren Gedanken. So dass Sie sich entschloss, ein Tagebuch bei McPapier zu kaufen und Ihre Gedanken, mithilfe von himmelsblauer Tinte auf schneeweißem Papier, festzuhalten:
Oh mein Gott. Man schaue sich doch bitte die Changeset Nummer 5223 an. Still und heimlich wurde also vor ein paar Tagen der Rails Core um die Bibliothek ActiveSupport::Multibyte erweitert. Was heißt das für uns? Wir können nun unsere kryptischen, typisch deutschen Namen ohne irgendwelche Probleme in Rails Applikationen benutzen:
"Daniel Bovensiepen".reverse # => "nepeisnevoB leinaD" "Daniel Bovensiepen".length # => 18
Mhhhh.. verdammt, das ging auch schon früher. Aber was ist mit folgendem:
"Kläuschen Kleinfeld".reverse # => "dlefnielK nehcsu??lK" "Kläuschen Kleinfeld".length # => 20
In der neuen Rails Version sieht dies dann so aus:
"Kläuschen Kleinfeld".reverse # => "dlefnielK nehcsuälK" "Kläuschen Kleinfeld".length # => 19
Es ist bestimmt schon fünf oder sechs Jahre her, da habe ich zum Geburtstag Lego geschenkt bekommen. Aber nicht diese normalen Acrylnitril-Butadien-Styrol-Copolymerisat Kunstoff Klötzchen zum Verschlucken, sondern das sogenannte Lego Mindstorm.
Wer es nicht kennt => Lego Mindstorm ist ein Spielzeug zum Aufbauen von kleinen programmierbaren Dingern. Ich sage Dingern weil man wirklich alles mögliche damit bauen kann. So hatte ich z.B. ein kleines Fahzeug gebaut, welches extrem zielsicher durch die Wohnung meiner Eltern genau gegen das Schienbein meiner Mutter fährt. Ein weiteres Projekt zusammen mit dem Bausatz eines Freundes, war ein Cliffhanger der eine riesige (bestimmt 60cm!!!) Lego Wand hochklettert und durch einen gezielten Sprung in den Abgrund die Arbeit von Wochen zu nichte macht. Und was sehe ich heute auf Rubyforge? Eine Bibliothek für das neue Lego Mindstorm NXT. Mithilfe von Ruby und Bluetooth kann man dann seinem elektronischen Ding befehle senden. Wie Cool ist das denn?