07.07.08
Posted in Ruby On Rails, Allgemein
at 11:27:30
Wir unterbrechen dieses Blog für eine Nachricht in eigener Sache:
Ich suche einen Ruby-on-Rails Softwareentwickler zur Festanstellung. Alternativ auch gerne einen Studenten für 15h/Woche.
Geforderte Fähigkeiten:
- Objektorientiertes denken
- Ruby / RubyOnRails oder zumindest sehr gute OO Kenntnisse
Das Projekt:
- Sehr spannender und bekannter Startup
Einsatzort: Zwischen Köln und Düsseldorf.
Bei interesse, einfach per Mail melden.
Permalink
16.06.08
Posted in Ruby On Rails, Projektmanagement
at 10:54:05
Ich letzter Zeit habe ich eine größere Rails-Anwendung debugged. Dabei habe ich etwas über einige Stolperfallen gelernt. Wer also ähnliche Probleme hat, hier ein paar Tipps:
Niemals Mongrel und PStore zusammen einsetzen
Wir hatten einige Probleme mit Session-Handling. Der Grund lag daran, dass wir die Sessions im Filesystem gespeichert haben. Laut Mongrel-FAQ soll man das auch nicht machen. Aber weder ich, noch verschiedenste Entwickler und Firmen die ich mit meinem Problem genervt hatte, kamen auf diese Lösung.
Also: Sessions immer in der Datenbank, oder im memcache speichern!
Rails hat große Timeout-Probleme
Wenn Rails bei memcache in einen Timeout läuft, kann sich Mongrel aufhängen. Prinzipiell scheint die IO-Lib von Rails suboptimal programmiert zu sein. Ich bin durch einen Blog-Eintrag bei Rapleaf darüber gestolpert. Dort findet sich auch ein Code-Schnippsel, um das Problem mit memcache zu lösen.
memcache und gettext mögen sich nicht
Der ist auch super. Gettext (dient zur Lokalisierung von Web-Seiten) und der memcache-Client arbeiten nicht vernünftig zusammen. Details und Lösung gibt es hier.
Wenn ich jetzt noch herausfinde, warum memcache Probleme mit dem automatischen expire hat, wird es ein guter Tag.
Permalink
06.06.08
Posted in Ruby On Rails
at 12:43:01
Nach mehreren schlaflosen Nächten habe ich mod_rails aus einem großen Projekt wieder entfernt.
Jetzt werkeln nginx&mongrel_cluster wieder.
Das Problem lag daran, dass mit mod_rails nach 4-5 Stunden der Server keine Anfragen mehr angenommen hat. Außerdem lief ständig der Speicher über.
Ich hoffe nun auf die nächste Version, vielleicht klappt es ja damit besser.
Permalink
04.06.08
Posted in Ruby On Rails, Projektmanagement
at 11:39:00
modrailsaka passenger ist wie mod_php für Rails (ja, jetzt wird es technisch).
Man kann mit passenger extrem einfach Rails Anwendungen unter Apache laufen lassen. Leider haben viele Leute Speicherprobleme im Zusammenhang mit passenger gemeldet. Ich hatte dazu letzte Nacht ein sehr seltsames Erlebnis:
Eine große Rails Anwendung sollte auf einen neuen (virtualisierten) Server umziehen. Sicherheitshalber habe ich dem Server 2GB Speicher gegeben. Leider schien dies für passenger nicht zu reichen. Selbst mit nur 3 oder 4 Instanzen habe ich den Speicher zu >80% verbraucht. Und nach spät. 1-2 Stunden fing die Maschine an zu swappen oder Apache wollte gar nicht mehr mitspielen.
Da ich aber mal schlafen wollte, habe ich den Server von 2GB auf 3GB erhöht. Das ging aber leider nicht, da nicht mehr gengu Speicher für diese virtuelle Maschine verfügbar war. Ok, aber 2.3GB waren möglich - besser als nichts.
Also die Maschine mit dem leicht höheren Speichern neu gestartet. Ergebnis: Statt 1.7GB haben die Anwendungen nur noch 500Mb Speicher verbraucht. Also hätten die 2GB auch gereicht…
Auf jeden Fall ist es extrem kompliziert, passenger und Apache vernünftig zu konfigurieren. Meine Ergebnisse bislang:
1. Lieber weniger Instanzen aufsetzen:
RailsMaxPoolSize 4
RailsPoolIdleTime 800
3 ist ok, ab 6 wird es bei mir komischerweise wieder langsamer. Standard für RailsMaxPoolSize ist 20 - das würde ich mich
nicht trauen.
RailsPoolIdleZime habe ich einfach hoch gesetzt. Warum sollte ich eine Instanz wieder beenden? Braucht duch nur Zeit zum Neustart. Die Gefahr ist natürlich, dass die einzelnen Prozesse immer mehr Speicher verbrauchen. Das werde ich beobachten.
2. Apache prefork vs. Apache worker: prefork
Bei den Einstellungen muss man einfach mal ein wenig experimentieren.
Hier sind meine, but ymmw:
StartServers 3
MinSpareServers 2
MaxSpareServers 4
MaxClients 50
MaxRequestsPerChild 0
Wenn das dann erstmal läuft, rennt der Server wirklich gut. Ich erkenne einen spürbaren Vorteil gegebenüber einem mongrel-cluster
Permalink
17.04.08
Posted in Ruby On Rails
at 16:03:09
Mal angenommen, man betreut eine recht erfolgreiche Webseite.
Und mal weiter angenommen, man speichert die Sessions im Dateisystem.
Und - nur mal so - angenommen, man würde aus irgendwelchen Gründen jetzt auch immer, diese Sessions monatelang nicht löschen.
Wie lange dauert es dann wohl, > 2 Mio. Session-Dateien per “rm *” aus dem Verzeichnis zu löschen?
Richtige Antwort: Erstaunlich(*) lange.
Dinge, die man nur einmal falsch macht (bevor sich Hohn und Spott über mich ergießt, ich war nicht der Verursacher, ich habe es nur entdeckt)…
(*) Erstaunlich = Eine ganze Nacht
Permalink
14.04.08
Posted in Ruby On Rails
at 12:55:16
Bei aller Begeisterung für RubyOnRails gab es bislang immer eine unschöne Hürde: Kaum ein Massenhoster hat RoR unterstützt. Wer eine Raisl Applikation schreiben wollte, brauchte einen eigenen Root-Server.
Dazu kommt noch, dass es verschiebene Wege gibt, die Applikation zu betreiben. FCGI, Mongrep, Thin, ebb - so 100% hat sich noch nichts durchgesetzt. Auch wenn die Kombination aus Apache und Mongrel wohl die meisten User hat.
Das Problem war, dass es nicht so etwas wie z.B. mod_php gab - also eine extrem simple Möglichkeit, um Rails Programme auszuführen.
Das hat sich (hoffentlich) nun geändert. mod_rails (http://modrails.com/index.html) verspricht genau dieses Problem zu lösen. Es ist binne Minuten installiert und schon muss man sich um nichts mehr kümmern.
mod_rails ist eine kommerzielle Entwicklung die als Freeware veröffentlicht wurde.
Ich habe es auf einigen Testservern installiert und bin echt begeistert. Schnell, einfach, stabil - was will man mehr
Permalink
05.03.08
Posted in Ruby On Rails
at 15:53:42
Als Java populär wurde, gab es einige mittlerweile legendäre Projekte die an die Wand gefahren wurden. So gab es z.B. den Versuch, ein Office Paket vergleichbar mit MS-Office durch ein Java-Applet zu realisieren. Dummerweise war das Applet zu groß, dass damals die Ladezeiten unerträglich waren.
Auch das Projekt Cheops ist sicherlich noch einigen in Erinnerung.
Die Argumente der Java Gegner waren in etwa:
Java ist viel zu langsam, J2EE ist viel zu komplex, Java skaliert nicht, Java/J2EE bringt keine Vorteile gegenüber etablierten Ansätzen. Jedes gescheiterte Projekt war Wasser auf die Mühlen der Gegner.
Und wenn schon Java, dann aber Schnittstellen per CORBA um keine Insellösung zu bauen.
Ich habe in der Zeit sehr viele, sehr lange Gespräche mit Kunden gehabt und immer wieder auf die Vorteile von J2EE verwiesen. Teils aus Überzeugung, teils weil es mein Job war.
Wenn ich nun die Argumente gegen RubyOnRails höre, fühle ich mich doch irgendwie ein klein wenig in diese Zeit zurückversetzt. Allerdings mit umgekehrten Rollen. Damals waren die Java-Jungs die coolen Rebellen die gegen C++ und Co. zu Felde zogen.
Heute sind die RoR Jungs die coolen Rebellen und J2EE alt und etabiert.
Meine Meinung nach einigen RoR Projekten: RoR löst die Versprechen ein, die J2EE gegeben hat.
Endlich ist es tatsächlich möglich, schnell und einfach Komponenten zu bauen, auf die andere Anwendungen zugreifen können (an dieser Stelle natürlich der Hinweis, dass es nicht nur ein Verdienst von RoR, sondern auch und gerade ein Verdienst von RESTFull WebServices - dazu schreibe ich später mal etwas). Auch kann ich jetzt Software entwickeln, während mein Kunde neben mir sitzt und auf Änderungswunsche schnell und flexibel reagieren.
RoR macht aus einem Deppen keinen hervorragenden Entwickler, aber es macht aus einem guten Entwickler einen noch produktiveren Entwickler.
Permalink
20.02.08
Posted in Ruby On Rails
at 13:26:14
Erwähnte ich schon, dass ich ein großer Ruby On Rails Fan geworden bin? Ach, nur 100 Mal? Ähm, ok…
Wer Lust auf einige nette Tipps und Tricks hat, findet hier einige nette Anleitungen:
http://railscasts.com/
Permalink
12.11.07
Posted in Ruby On Rails
at 13:03:45
Es gibt ja in der Physik das Gesetz, dass man durch die Messung das Ergebnis beeinflusst. Wenn man z.B. den Ort eines winzig kleinen Teilchens messen will, muss man es sehen. Das bedeutet, man beschießt es mit Licht (besser, mit Photonen). Und dadurch wird das Teilchen beschleunigt (Unschärferelation)
Bei mir war das so:
Meine Internet Lernkartei (http://www.web-lernbox.de) hatte “Schluckauf”. Nachdem ich ein wenig am Server umgestellt hatte, antwortete die Seite manchmal nicht mehr. Auch der Wechsel von einem Server zu einem Mongrel-Cluster half nicht (machte es nur noch schlimmer, aber das habe ich erst später verstanden). Kurzer Einschub: Mongrel ist ein Server für RubyOnRails.
Um zu verstehen, wann der Fehler auftritt, habe ich Monit installiert. Monit ist ein sehr nettes Überwachungstool. Es ist einfach zu konfigurieren und kann Server selbstständig wieder starten.
Um nun Mongrel mit Monit zu überwachen, habe ich also folgendes gemacht:
- Monit herunterladen
- entpacken,
- der klassische Unix-Dreisprung: ./configure, ./make, ./make install
Meine Konfigurations sieht ungefähr so aus:
set daemon 60
set httpd port XXXX and
use address localhost # only accept connection from localhost
allow localhost # allow localhost to connect to the server and
##### mongrel 8000 #####
check process mongrel-8000 with pidfile /[PFAD ZUR WEB-LERNBOX]/log/mongrel.8000.pid
group lernbox
start program = "/usr/local/bin/ruby /usr/local/bin/mongrel_rails start -d -e production -p 8000 -a 127.0.0.1 -P /[PFAD ZUR WEB-LERNBOX]/log/mongrel.8000.pid -c /[PFAD ZUR WEB-LERNBOX]"
stop program = "/usr/local/bin/ruby /usr/local/bin/mongrel_rails stop -P /[PFAD ZUR WEB-LERNBOX]log/mongrel.8000.pid"
if totalmem is greater than 90.0 MB for 5 cycles then restart # eating up memory?
if cpu is greater than 50% for 2 cycles then alert # send an email to admin
if cpu is greater than 80% for 3 cycles then restart # hung process?
if loadavg(5min) greater than 10 for 8 cycles then restart # bad, bad, bad
if 3 restarts within 5 cycles then timeout # something is wrong, call the sys-admin
if failed port 8000 protocol http # check for response
with timeout 10 seconds
then restart
Das ganze muss leider für alle Mongrel Instanzen wiederholt werden. Monit kann natürlich alle Dienste überwachen. Hier ist eine nette Beispielkonfiguration.
Was passiert also: Monit schaut alle 60 Sekunden nach, ob meine Lernbox noch lebt.
Tja, und was ist passiert? Die Box stürzte nicht mehr ab. Durch die Messung wurde das Problem behoben.
Mittlerweise habe ich es auch verstanden. Es ist ein Bug: Die Datenbank (MySQL) bekommt einen Timeout, Mongrel wartet aber immer noch auf die Antwort. Dadurch hängt der Server. Durch die ständige Messung habe ich den Timeout natürlich verhindert. Und durch den Mongrel-Cluster habe ich es erst richtig schlimm gemacht. Nachts lernt natürlich kaum jemand. Also war wenig los und die Server haben sich reihenweise verabschiedet…
Wie auch immer: Wer sich in den letzten Tagen geärgert hat, weil er die Lernbox nicht erreichen konnte: Geht wieder…
Permalink
31.10.07
Posted in Projekt P, Ruby On Rails
at 12:39:55
Die letzten Tage habe ich ja Newsletter und Benutzerverwaltung eingebaut. Was noch fehlt, ist eine Admin-Oberfläche um “mal eben” Daten zu ändern.
Nun bin ich ja erstmal faul. Also programmiere ich das nicht selber, sondern suche mir einen schon vorhandenen Generator. Eigentlich könnte man es natürlich auch schon mit Boardmitteln machen.
script/generate scaffold Modell-Name
erzeugt schließlich die rudimentären Oberflächen, um Daten zu bearbeiten. Aber auf der einen Seite sieht das nicht sonderlich hübsch aus und darüber hinaus haben wir dann noch keine Relationen abgedeckt. Gut, dass es noch andere Generatoren gibt.
Die Kandidaten sind:
Streamlined
Active-Scaffold und
Hobo
Hobo ist allerdings zuviel des Guten, damit kann man eher komplette Anwendungen bauen. Es spielt damit in der gleichen Liga wie z.B. Goldberg.
Goldberg hatte ich tatsächlich ins Auge gefasst, da ich eh’ auch ein wenig CMS brauche. Aber leider ist mein Design zu komplex dafür.
Wie auch immer. Gewonnen hat Active-Scaffold.
Prinzipiell nutzt man in der Railsentwicklung sehr viele Plugins und Generatoren. Da diese Generatoren normalerweise recht wenig Code erzeugen kann man das Ergebnis gut verstehen und weiterentwickeln.
Die Installation und Konfiguration von Active-Scaffold ist erschreckend simpel. Super, also weiter zum CMS.
Permalink
26.10.07
Posted in Projekt P, Ruby On Rails
at 16:43:26
Auf der Seite wird man sich als Benutzer registrieren können. Also brauche ich eine Benutzerverwaltung (Registrierung, Login, etc.).
Auch hier bin ich faul. Ich nutze einfach acts_as_authenticated.
acts_as_authenticated ist ein Generator der mir die grundlegenden Funktionen generiert. Wie schon bei der Newsletter wird es auch hier einen Registrierungscode geben, den man per Mail zugeschickt bekommt.
Das vorgegebene User-Datenmodell erweiter ich um einige Funktionen. Unter anderem kann man mehrere Adressen hinterlegen.
Also gibt es ein neues Modell namens “address”. Das Usermodell erweiter ich um den Befehl
has_many :addresses
Entsprechend kommt an das Addressenmodell:
belongs_to :user
Und schon habe ich eine saubere 1:N Beziehung definiert.
… Fast. Denn wenn ein User gelöscht wird, brauchen wir die Adressen natürlich nicht mehr. also
sieht es im Usermodell tatschlich so aus:
has_many :addressed :dependent => :destroy
Jetzt sieht es gut aus. Man könnte auch destroy_all schreiben, dann werden die Objekte sofort gelöscht. So wird vorher noch before_destroy und after_destroy für jedes Objekt aufgerufen. Es ist also langsamer. Aber die Benutzer sollen sich schließlich anmelden und nicht alle wieder löschen…
Jetzt kommt die Kür. Jeder User hat viele Adressen, aber eine Hauptadresse. Die Hauptadresse will ich einfacher finden und erweiter mein Usermodell so:
has_one :mainaddress, :class_name=>'Address', :conditions =>'addresses.primaereadresse=true'
Das Ergebnis: Auf die Hauptadresse kann ich nun in meinem Programm über User.mainaddress problemlos zugreifen. Schick, oder?
Zeitaufwand: ca. 2 Stunden. Allerdings habe ich das Design noch nicht optimiert. Aber das kommt später.
Permalink
25.10.07
Posted in Projekt P, Ruby On Rails
at 12:34:58
Bei der Entwicklung der Seite werde ich die wichtigsten Funktionen zuerst entwickeln. Sollte irgendetwas gründlich schief laufen, sollen sich die Kunden zumindest schon mal als User registrieren können und eine Newsletter empfangen können.
User und Newsletter-Empfänger trenne ich dabei. Die Newsletter wird - klar - durch ein DoubleOptIn Verfahren abonniert werden. Das heißt, dass man sich auf der Seite anmeldet und anschließend einen Bestätigungslink zugeschickt bekommt. Ich brauche allerdings noch ein wenig mehr. Ich möchte neben der Mailadresse auch Name und Anschrift des Abonnenten haben (natürlich freiwillig).
Also sieht mein Prozess so aus:
1. Kunde trägt seine Mailadresse auf der Seite ein
2. Kunde bekommt eine Mail mti einem Bestätigungslink
3. Kunde ruft den Link auf und gibt anschließend weitere Daten ein
4. Datensatz wird aktiviert.
Ok, wir brauchen also zuerst eine Tabelle um die Daten abzulegen.
script/generate modell subscriber
Jetzt schnell die Attribute definiert:
CreateSubscribers < ActiveRecord::Migration
def self.up
create_table :subscribers do |t|
t.column :name, :string
t.column :vorname, :string
t.column :strasse, :string
t.column :plz:string
t.column :ort:string
t.column :mail, :string
t.column :created_at, :date
t.column :updated_at, :date
t.column :activation_code, :string, :limit => 40
t.column :activated_at, :datetime
end
end
def self.down
drop_table :subscribers
end
end
Und die Tabelle anlegen:
rake db:migrate
created_at und updated_at sind besondere Fehler. Rails wir diese Felder selbstständig füllen.
Um sein Abo zu aktivieren, braucht der Kunde einen Aktivierungslink. Wir brauchen also einen Schlüssel, den wir in den Link einbauen. Das machen wir in der Klasse Subscriber so:
class Subscriber < ActiveRecord::Base
before_create :make_activation_code
def make_activation_code
self.activation_code = Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )
end
(...)
end
So, jetzt kann ich den controller erzeugen und mir die notwendigen Methoden bauen. Diese sind:
- activate (hier frage ich den weiteren Kundendaten)
- activate_step2 (hier speichern wir die Daten)
Und schon bin ich fertig.
Ach, mist. Da habe ich doch glatt etwas vergessen. Ich möchte dem Abonnenten die Möglichkeit geben, sich durch einen einfachen Link wieder abzumelden. Dazu muss ich aber eine Schlüssel speichern aus dem ich den Link erzeuge (also wie der activation_code, den ich dem Kunden schicke. Unter Ruby on Rails ist das aber kein Ding:
script/generate migration subscriber_deactivationcode
erzeugt mir eine neue Migrationsdatei.
Die nur schnell ausfüllen:
class Subscribers3Deactivationcode < ActiveRecord::Migration
def self.up
add_column :subscribers, :deactivation_code, :string, :limit => 40
end
def self.down
remove_column :subscribers, :deactivation_code
end
end
Ok, eigentlich müsste die die vorhandenen Datensätze updaten. Aber ich habe ja nur Spieldaten, also was soll’s. Jetzt noch schnell make_activation_code erweitern:
self.activation_code = Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )
Fertig!
Ich habe natürlich nicht alles beschrieben. Der Kunde bekommt natürlich einige Mails zugeschickt. Das ist aber nicht sonderlich spektakulär. Außerdem habe ich einige Tests geschrieben, um meine Entwicklung zu überprüfen.
Zeitaufwand für das Feature? 1/2 Tag.
Geschwindigkeitsvorteil gegenüber normaler (J2EE) Entwicklung: Gering, in Jave würde man es ähnlich machen. Allerdings musste ich nicht ständig meine Arbeit übersetzen und auf einen Testserver deployen, sondern konnte direkt aus der Entwicklungsumgebung (netbeans 6) “run file” aufrufen und habe dadurch sehr schnell meine Entwicklung testen können.
Permalink
24.10.07
Posted in Projekt P, Ruby On Rails
at 10:28:37
Auch nach vielen Jahren bei verschiedenen Web-Agenturen haben sich meine zeichnerischen Fähigkeiten nicht wirklich verbessert. Ich hatte schon in der Schule eine 3- in Kunst. Bilde mir zwar ein, Design beurteilen zu können. Aber damit muss ich es sja noch lange nicht selber können.
Also gebe ich das Design an eine externe Agentur. Auf der erstellten Grafiken werden dann die HTML Template gebaut. Das könnte ich zwar eigentlich einigermaßen selber. Aber die Zeit drängt. Daher wird die initiale Erstellung durch einen externen HTML’er durchgeführt. Dies nutze ich dann zusammen mit masterview als Basis meiner Entwicklung.
Das führt uns zu der Frage: wann delegieren, wann selber machen? Viele Menschen haben Probleme, Aufgaben zu delegieren. Das hat einen einfachen Grund: Entweder man kann die Aufgabe selber nicht durchführen. In dem Fall kann man auch die Qualität der Arbeit schlecht bewerten. Man kann das Ergebnis zwar beurteilen. Aber vielleicht hätte man es noch besser oder schneller machen können. Leider kann man es nicht beurteilen.
Oder man ist bei dem Thema selber gut. In dem Fall geht viele Leute ihren Mitarbeitern auf die Nerven, weil diese die Aufgabe scheinbar nicht gut genug erfüllen. Wie auch, wenn der Chef ihnen das immer wieder weg nimmt …
Gerne hört man das Sprüche wie “Das kann sonst niemand richtig”, “Wenn ich es nicht selber mache, herrscht hier das Chaos” usw. usw.
Es gibt auf der anderen Seite z.B. die Regel, dass Leiter von Entwicklungsteams ab einer Teamgröße von 7 Personen nicht mehr selber programmieren sollten. Auch das halte ich mittlerweile für zu einfach formuliert. Warum sollte man nicht selber in die Tasten greifen, solange das Team nicht auseinanderfällt?
In meinem aktuellen Fall gibt es zwei einfache Parameter: Zeit und Geld. Ich habe ein sehr geringes Budet (vor allem ist es mein eigenes Geld …) und ich habe feste Zeitvorgaben. Daraus will ich eine möglichst hohe Qualität holen - also ein Aufgabe aus dem Bereich der linearen Optimierung
Allgemein würde ich folgende Regel aufstellen: Es ist einfacher, Aufgaben nachträglich wieder an sich zu ziehen als nachträglich abzugeben. Also sollte so viel wie möglich abgeben und sich auf die Qualitätssicherung konzentrieren.
Permalink
22.10.07
Posted in Projekt P, Ruby On Rails
at 12:21:27
Es wird mal wieder Zeit für ein neues Projekt. Diesmal gibt es einige Besonderheiten. Normalerweile arbeite ich ja als freier Berater meistens als Projektleiter beim Kunden vor Ort. Diesmal erstelle ich für den Kunden die komplette Applikation (natürlich in Ruby on Rails) selber und arbeite im Home Office. Damit bin ich zum ersten Mal seit über 7 Jahren fast täglich zuhause.
Nach der Web-Lernbox ist das damit mein zweites RoR Projekt. Diesmal allerdings in groß …
Würde ich das Projekt klassisch kalkulieren (z.B. als J2EE Anwendung mit einem entsprechenden Team), käme ich auf Kosten von ca. 150.000 EUR Kosten. Mein Ziel ist es, das ganze für ca. 50.000 EUR zu schaffen (dabei setze ich meinen normalen Tagespreis an). Allerdings bekommen ich das Geld nicht, sondern werde mich später am Ergebnis beteiligen - aber das ist eine andere Geschichte und die soll ein anderes Mal erzählt werden.
In den nächsten Wochen wird es hier also in lockerer Folge meine Erfahrungen bei der Entwicklung einer größeren Anwendung mit Ruby On Rails geben.
Möge die Übung gelingen.
Permalink
02.10.07
Posted in Ruby On Rails
at 12:15:39
Ich habe mir in letzter Zeit ein paar Entwicklungsumgebungen für RoR (Ruby On Rails) angeschaut. Hier mein subjektives Fazit:
1. Der reine Editor: JEdit
JEdit ist ein wenig der Emacs des 21. Jahrhunderts - der kann alles.
Das Ruby-Plugin kennt CodeCompletion, kann (einigermaßen gut) Klassen erkennen und die entsprechenden Mathoden anbieten und kennt natürlich Syntax-Highlightning.
2. RadRails / Aptana
RadRails basiert auf Eclipse . Zuerst die gute Nachricht: Wenn man InstantRails unter Windows einsetzt, kann man den Arbeitsbereich auf das Verzeichnis legen. Weitere Konfigurationen sind nicht notwendig. Das war aber auch schon alles, was mir gefällt. Die Code-Vervollständigung ist gefühlt schlechter als bei JEdit. Dafür kann man einigermaßen konfortabel Gems installieren. Aber alles in allem hat es mich nicht umgehauen.
3. 3rd Rail
Ich habe meine erstes Geld als Softwareentwickler mit Turbo-Pascal verdient (oder Clipper? Ach, egal). Der Anbieter, Borland, hatte immer einen guten Ruf. Als ich das erste Mal “Delphi 1.0″ sah, war ich schlicht und einfach überwältigt. So musste Softwareentwicklung aussehen (ok, die dunklen Seiten habe ich auch recht schnell kennen gelernt). Trotzdem noch heute hängt an meiner Pinnwand die Eintrittskarte zum “Borland European Software Festival” - das muss so 1991 gewesen sein. Mittlerweile nennt sich die Sparte welche Entwicklungstools anbietet Codegear. Als ich hörte, dass Codegear ein RoR war ist sehr, sehr gespannt.
Tja, aber was soll man sagen 3rd Rails basiert wie RadRails auf Eclipse. Ich habe kein Feature gefunden, was mich auch nur ansatzweise umgehauen hätte. Also vergessen wir das schnell wieder.
3. Netbeans 6.0 (Beta)
Netbeans wurde von SUN zusammen mit Java auf den Markt geworfen. Es ist eine in Java geschriebene Java-Entwicklungsumgebung. Die ersten Versionen waren unglaublich schlecht. Langsam, buggy, seltsam zu bedienen. Alles in allem eher eine Warnung als eine Werbung für Java.
Netbeans 6 kann nun (neben Java, UML und anderen Dingen) auch Rails.
Und damit kommen wir auch zum absoluten Siegern: Netbeans 6 rockt.
Die Code-Vervollständigung ist super, analysiert den Code sauber und liefert die richtigen Methoden. Rails wird vorbildlich unterstützt. Ein Beispiel: Wie migriert man die Datenbank unter 3rdRail? Man muss auf die Console gehen, und dort per Hand “rake db:migrate” eingeben. Wow, dafür brauche ich keine Entwicklungsumgebung.
Netbeans? Mit dem Menüpunkt “Migrate Database”. Anschließend werden einem die möglichen Versionen zur Auswahl angeboten. Neue Generatoren, neue Gems? Alles kein Problem.
Mal eben eine Funktion ausprobieren? Methode im Editor auswählen, rechte Maustaste “run File” - fertig.
Und das Beste: Der Support von Subversion (Versionierungstool) ist super.
Permalink
27.09.07
Posted in Ruby On Rails
at 09:40:37
So schön Sprachen wie RubyOnRails auch sind, es gibt einen kleinen Nachteil: Das Design der Oberfläche ist eher suboptimal. Eigentlich würde man ja gerne “mal eben” mit einem WYSIWYG-Tool das Benutzerinterface malen, das klappt aber leider nicht.
In Rails definiert man ein Eingabefeld z.B. so :
< %= text_field("user","name") %>
Rails baut daraus anschließend die HTML-Sicht. Das ist zwar alles schon und praktisch, sieht nur in einem HTML-Editor doof aus. Jetz mag man zwar einwenden, dass echte Programmierer keine WYSIWYG-Editor benutzen, aber echte Programmierer würden eh nicht Rails oder HTML programmieren.
Die Lösung lautet: Masterview . Masterview ist quasi der Leim zwischen Dreamweaver (oder nvu oder was für ein HTML Editor auch immer) und Rails. Kurz ausgedrückt versteckt Masterview die Rails-Kommandos in XML Tags.
Unser obiges Beispiel sieht dann so aus:
input name=”name” type=”text” mv:text_field=” ‘user’,'name’”
Ergebnis: Das lässt sich auch ohne Rails in jedem Browser darstellen und in einem Editor bearbeiten.
Aber Masterview kann noch mehr.
Rails kennt ja die Möglichkeit, Teile einer Seite in Layouts zu lagern. Das ist extrem praktisch, da man wiederkehrende Elemente nur einmal definieren muss. Dumm nur, dass man in so einem Fall mindestens zwei Dateien hat, nämlich die Layout Datei und die “eigentliche” Datei. Wenn man jetzt noch Teile seiner Seite mit Ajax dynamisch aktualisieren will, hat man eine dritte Datei (welche mit render :partial eingebunden wird).
Unter Masterview packt man alles in eine einzige HTML-Datei.
Mit den Befehlen mv:generate und mv:gen_partial kann man dort die Generierung der benötigten Dateien anstoßen.
Man kann Masterview problemlos ausprobieren. Da es (auf Wunsch) *.rhtml Dateien erzeugt, ist der Wechsel zurück zur “normalen” Entwicklung kein Problem.
Permalink
25.09.07
Posted in Ruby On Rails, Projektmanagement, Allgemein
at 23:12:38
Hier mal ein kurzer Zwischenstatus meiner Internet Lernkartei (http://www.web-lernbox.de):
Mittlerweile werden rund 10.000 Lernkarten damit verwaltet. Für eine Testversion, nicht schlecht. Was ich auch sehr nett finde: Einige Lehrer haben ihre Schüler offensichtlich dazu “verdonnert”, die Lernbox zu nutzen - sorry Leute
Leider war ich mit meinem RubyOnRails-Hoster nicht 100% zufrieden. Daher ist der Auftritt auf einen Server umgezogen, den ich nun komplett selber verwalte. Nach einigen Kinderkrankheiten läuft der Auftritt auch stabil und schnell. Es hat allerdings ein wenig gedauert, wenn der Server so lief, wie ich wollte.
Leider sind durch diesen Umzug die anstehenden neuen Entwicklungen ein wenig aus dem Zeitplan geraten. Ich habe aber alle Anregungen der Nutzer notiert und werde mich in den nächsten Tagen an die nächsten Features machen.
Permalink
15.08.07
Posted in Ruby On Rails, Allgemein
at 14:12:20
Auf meiner Internet-Lernkartei namens Web-Lernbox kann man ja per Ajax nach Lernkarten suchen und in der Liste blättern (dies nennt man Pagination). Das Ergebnis sieht (zumindest in meinem Augen) recht ansprechend aus.
Hier die Details, wie man so einen Effekt recht einfach in Rails programmiert.

Phase 1: Das Suchfenster
Wir brauchen ein Textfeld. Wenn nun der Benutzer eine Eingabe tätigt, soll eine Aktion auf dem Server ausgeführt werden. Klingt schwierig, ist es aber nicht. So sieht der entsprechende Teil in der View-Datei aus:
(...)
< %= text_field_tag :filter %>
< %= observe_field(:filter,
:frequency => 0.2,
:update => “cardlist”,
:url => {:action => :filter_elements, :id => @box}) %>
Der erste Befehl ist klar. text_field_tag definiert ein Inputfeld. Anschließend definieren wir ein Observer_field. Der erste Parameter definiert das Feld, welches beobachtet werden soll. :frequency=>0.2 sagt, dass alls 0,2 Sekunden auf eine Änderung geprüft werden soll. Gibt der Benutzer etwas sein, wird die Methode “filter_elements” aufgerufen. Diese Methode bekommt den Paramenter id mit, damit wir wissen, welche Lernbox eigentlich gefiltert werden soll. Schließlich haben wir noch das Attribut :update=>”cardlist”. Das sagt, welcher Bereich eigentlich nach dem Aufruf neu beschrieben wird (wir wollen ja nicht die komplette Seite neu zum Client schicken, sondern nur das Ergebnis).
In dem View gibt es also einen Bereich “cardlist” den habe ich in eine zweite Datei (_cardlist.rhtml) gepackt und rufe ihn im View über
< %= render( :partial =>‘edit/cardlist’ ) %>
auf.
Wichtig ist natürlich, dass in der Datei cardlist ein Bereich mit der id “cardlist” definiert ist:
Datei _cardlist.rtml:
<div id="cardlist">
<table cellpadding="5" class="edit_list_table" width="100%">
(... Anzeige der Elemente... )
</table>
</div>
Das war bislang einfach, oder? Also weiter.
Phase 2: Die Ajax-Suche
In meinem Controller sieht die Suchmethode nun so aus:
def filter_elements
filter_name = request.raw_post
box_id = current_user.Boxes.find(params[:id]).id;
@cards_pages, @cards = paginate(:cards, :conditions => ['(frage like ? or antwort like ?) and box_id = ?',
filter_name, filter_name, box_id])
render :partial => 'cardlist'
end
Kleine Anmerkung: Ok ok, in Wirklichkeit sieht die Funktion bei der echten Lernbox ein wenig anders aus, aber es geht ja ums Prinzip. Es passiert hier also folgendes. Für Für jeden Filteraufruf wird der Datenbestand neu gefiltert und mit dem Befehl paginate in mehrere Seiten geteilt.
Phase 3: Blättern mit Ajax
Jetzt gibt es aber noch ein Problem. Die Paginate Funktion existiert schon in Rails und kann mit dem Befehl “pagination_links” im View auf die entsprechenden Navigationselemente erzeugen. Dann würde aber die komplette Seite neu aufgerufen und nciht per Ajax nur der notwendige Bereich neu geschrieben. Also musste ich mir einen kleinen Helfer schreiben. In die _cardlist.rhtml kommt:
< %= draw_paginator(@cards_pages) %>
Jetzt muss man nur noch der Helper entsprechend erweitern:
def my_pagination_links(paginator,action)
if paginator then
pagination_links_each(paginator,{:link_to_current=>false}) do |n|
link_to_remote(n.to_s, { :url=>{:action=>action, :page =>n.to_s}, :update=>'cardlist' })
end
else
return ''
end
end
def draw_left_paginator(paginator,action)
if paginator.current.previous then
link_to_remote('
‘,
:url=>{:action=>action, :page =>paginator.current.previous}, :update=>’kart_list’)
else
return ”
end
end
def draw_right_paginator(paginator,action)
if paginator.current.next then
link_to_remote(’
‘, :url=>{:action=>action,
:page =>paginator.current.next}, :update=>’kart_list’)
else
return ”
end
end
def draw_paginator(paginator,action=’list’)
if paginator then
return draw_left_paginator(paginator,action) + my_pagination_links(paginator,action) + draw_right_paginator(paginator,action)
else
return ”
end
end
(Auch hier: der echte Code sieht anders aus)
Im Prinzip habe ich die ursprünglichen Pagination Sourcen genommen und verändert. Klar, man hätte auch einfach die entsprechende Methode überschreiben können. Aber so fand ich es sinniger.
Das war es auch schon. Der Aufwand für das Ajax-Frontend ist faktisch genauso hoch, wie bei einer normalen Seite, sieht aber viel hübscher aus.
Permalink
10.08.07
Posted in Ruby On Rails, Allgemein
at 12:13:21
Also eigentlich wollte ich jezt stolz über die neuesten Fortschritte der Web-Lernbox berichten.
- Man kann nun Boxen so freigeben, dass Nutzern sie nicht bearbeiten dürfen.
- Es gibt einen neuen Lernmode bei dem die Antwort bei der Eingabe schon geprüft wird
- Viele Fehler wurden behoben
- Bei Aufruf der Seite bekommt das Eingabefeld den Focus
Allerdings muss ich gerade zu meinem Schrecken feststellen, dass die komplette Seite nicht funktioniert, da der Zugriff auf das public Verzeichnis gesperrt ist.
Das ist schon das 2. Problem binne weniger Wochen.
Grummel, kennt jemand einen guten Hoster für Rails?
Update:
So, jetzt geht es wieder. Der Hoster macht viele Fehler, meldet sich aber immer schnell …
Der neue Lernmode ist bei den 1X1 Karten bereits eingerichtet. Probiert es mal aus.
Die nächsten Meilensteine:
- Lernkarten drucken
- Lehrermodus mit Auswertung des Lernfortschritts der Schüler
- (…) Ich bin für Vorschläge immer offen
Permalink
06.08.07
Posted in Ruby On Rails, Projektmanagement, Allgemein
at 09:22:22
Wie der ein oder andere Leser vermutet haben mag, habe ich die letzten Tage mit Ruby On Rails gespielt. Hier ist das erste Ergebnis, die
Web Lernbox:
http://www.web-lernbox.de
Dabei handelt es sich um die Online-Version einer Lernkartei.
Eine Lernkartei besteht aus (meistens) 5 Fächern und hilft dabei, z.B. Vokabeln zu lernen. Man nimmt eine Karteikarte und schreibt auf eine Seite die Frage, auf Rückseite die Antwort. Anschließend legt man die Karten in Fach 1 der Kartei. Wenn man nun lernt, fängt man vorne in der Kartei an und arbeitet sich durch: Kann man die Frage auf der Karte bearbeitet, wandert die Karte ein Fach weiter. Macht man einen Fehler, landet die Karte in Fach 1. Ist eine Karte irgendwann in Fach 5 angekommen (man hat also 5x hintereinander die Antwort gewusst), hat sich der Stoff im Langzeitgedächtnis verankert. 10-15 Minuten Training pro Tag reichen dabei völlig aus.
Meine Online Lernbox erweitert das Prinzip noch ein wenig. Karten werden nur einmal täglich erfragt. Außerdem werden Karten in den hinteren Fächern erst mit einigen Tagen Verzögerung abgefragt.
Angelegte Lernboxen können für andere Benutzer freigegeben werden.
Die aktuelle Version bietet noch nicht alle geplanten Funktionen, Erweiterungen sind aber schon in Planung. So wird es verschiedene Lernmodi sowie eine Druckfunktion geben. Darüber hinaus kann bestimmen, ob eine freigegebene Lernkartei durch andere Benutzer verändert werden kann.
Wer Lust hat, kann gerne einen Blick darauf werfen. Einige Lernboxen sind bereits freigeschaltet (u.a. Austragungsorte der Olympischen Sommerspiele sowie Deutsche Meister im Fußball - braucht man ja spätestens, wenn man sich bei Wer Wird Millionär anmeldet)
Ich würde mich über Feedback, Anregungen oder Fehlermeldungen sehr freuen.
Permalink