Ruby on Rails & Ajax
Telefonliste mit Ruby on Rails

DeveloperIT-ProjekteSoftware

MVC-Architektur

Ruby on Rails & Ajax

Schon der erste Beitrag zu Ruby on Rails (Internet Professionell 4/2006, Seite 80) hat gezeigt: Das Webframework ist konsequent, und einfache Anwendungen sind schnell aufgebaut. Aber die Entwicklung erfordert auch ein wenig Umdenken. Das strenge Denken aus MVC-Sicht ist nicht jedermanns Sache. Ruby on Rails unterteilt jede Anwendung in das Model, das für die Datenanbindung zuständig ist, den Controller, der die Steuerung übernimmt, und die View für die Präsentation. Ins Deutsche übertragen steht MVC übrigens für Modell, Präsentation und Steuerung oder kurz MPS.

Im Beispiel des ersten Beitrags fehlte noch die Präsentationsschicht. Sie soll hier dazukommen. Außerdem wird sie noch mit einer einfachen Ajax-Anwendung verbunden. Als Beispiel dient eine Telefonliste für Mitarbeiter, wie sie in vielen Intra- und Extranet-Anwendungen zum Einsatz kommt. Das Hauptaugenmerk liegt dabei auf der Demonstration der Fähigkeiten von Ruby on Rails. Als Basis zum Testen dient hier ein per Instant Rails aufgesetztes Ruby-on-Rails-System unter Windows, das Webserver und MySQL-Datenbank schon enthält.

Das Grundgerüst

Ruby on Rails & Ajax

Als Erstes benötigen Sie die Rails-Anwendung. Dies erledigen Sie über die Konsole respektive Eingabeaufforderung (Start, Programme, Zubehör, Eingabeaufforderung). Sie können die Anwendung in einem beliebigen Verzeichnis erstellen, empfehlenswert ist aber das Rails-Anwendungsverzeichnis. Es liegt bei normaler Installation unter rails_apps. Bei Instant Rails unter Windows kann das Verzeichnis also zum Beispiel auf C: liegen und InstantRails heißen:

cd c:\InstantRails\rails_apps\

Um die Anwendung zu erstellen, genügt folgender Befehl:

rails telefonliste

Der Name der Anwendung ist dabei relevant, da er später im Rails-Server zum Aufruf genutzt wird. Ruby on Rails unterscheidet hier wie auch bei allen anderen Angaben außerdem strikt zwischen Groß- und Kleinschreibung.

Wenn Sie den Befehl ausgeführt haben, entsteht automatisch ein Anwendungsverzeichnis mit festgelegter Struktur. Die wichtigsten Verzeichnisse sind config mit der Datenbankkonfiguration und app mit den Bestandteilen der Anwendung. Im Letztgenannten stecken dann Modelle, Controller und Views.

Als Nächstes müssen Sie die Datenbank anlegen. Da es sich um eine normale MySQL-Datenbank handelt, können Sie dazu jede beliebige Verwaltungsoberfläche verwenden. Wenn Sie Instant Rails einsetzen, ist dort bereits eine Instanz von phpMyAdmin mitgeliefert. Um sie aufzurufen, starten Sie zuerst über das Instant-Rails-Dialogfenster Apache und MySQL. Dann rufen Sie über das Menü auf der linken Seite (I-Symbol) den Befehl Configure, Database (via PhpMyAdmin) auf. Damit wird phpMyAdmin aufgerufen. Alternativ geht es über http://127.0.0.1/mysql/.

Die Datenbank selbst erhält den Namen telefonliste. Sie enthält eine Tabelle mit dem Namen lists. Der englische Plural ist für Ruby on Rails entscheidend, da dank des Active-Record-Prinzips aus dem Singularnamen des Modells automatisch der Tabellenname gemacht wird. Das wichtigste Feld ist der Primärschlüssel mit dem Namen id. Die übrigen Felder lassen sich natürlich frei nach Anforderung festlegen.

Modell

Ruby on Rails & Ajax

Um die Datenbank in Ruby anzumelden, registrieren Sie in der Datei database.yml im Verzeichnis config die Datenbank. Der Einfachheit halber sind hier Entwicklungs-, Test- und Produktivdatenbank jeweils dieselbe Datenbank. Die Datenbank kommt bei Instant Rails ohne Passwort aus, was nur für Testsysteme vertretbar ist.

development:
adapter: mysql
database: telefonliste
host: localhost
username: root
password:

test:
adapter: mysql
database: telefonliste
host: localhost
username: root
password:

production:
adapter: mysql
database: telefonliste
host: localhost
username: root
password:

Als Nächstes geht es an das Modell. Das können Sie dynamisch von einem der Helfer-Skripts von Ruby on Rails generieren lassen. Diese Helfer-Skripts werden automatisch in das Verzeichnis script der vorher generierten Rails-Anwendung gelegt. Hier stehen beispielsweise Skripts zum Generieren (generate) und zum Löschen (destroy) von Elementen zur Verfügung.

Wechseln Sie dazu in der Konsole und dort in das Anwendungsverzeichnis. Bei Instant Rails gelangen Sie am schnellsten über das Menü (I-Symbol im Dialogfenster) und hier Rails Applications, Open Ruby Console Window dorthin. Von dort geht es weiter in die Anwendung, und dann wird das Modell generiert:

cd telefonliste
ruby script\generate model List

Das Modell selbst steckt in der Datei app/models/liste.rb. Vorsicht, die Datei ist in Kleinbuchstaben, das Modell dagegen mit großem Anfangsbuchstaben bezeichnet. Hier sind schon alle Informationen enthalten, die für den Kontakt zur Datenbank notwendig sind.

Steuerung

Ruby on Rails & Ajax

Den Controller erstellen Sie mit:

ruby script\generate controller List

Damit sind die Grundzüge der Anwendung gelegt. Den Controller finden Sie unter pp/controllers/liste_controller.rb. Dort lässt sich beispielsweise mit den schon aus dem ersten Beitrag bekannten Zeilen eine komplette Liste und eine Eingabemaske für neue Telefoneinträge anlegen:


class ListController < ApplicationController
scaffold :list
end

Starten Sie anschließend zu Testzwecken den Server. Wechseln Sie dazu in die Ruby-Konsole und dort in die Anwendung telefonliste. Geben Sie folgende Zeile ein:

ruby script\server

Der Server Webrick startet. Die Telefonliste ist unter http://localhost:3000/list/ erreichbar. Nun soll das Ganze noch um eine Präsentationsschicht erweitert werden. Dafür gestalten Sie eine Ajax-basierte Suche in den Daten. Für die Suche generieren Sie einen eigenen Controller:

ruby script\generate controller Suche

In diesen Controller schreiben Sie später die Aktion suche, die für das Finden des Eintrags in der Datenbank zuständig ist. Sie könnten diese Aktion alternativ auch im schon bestehenden Controller List hinzufügen.

Präsentation

Ruby on Rails & Ajax

Bevor es aber mit der Such-Logik weitergeht, zuerst die Präsentationsschicht. Hierzu legen Sie im Verzeichnis app/views/suche eine neue Vorlagedatei mit dem Namen suche.rhtml an. Ruby on Rails verwendet hier die eigene Dateiendung RHTML, nach der auch an Hand der jeweils angegebenen Namen automatisch gesucht wird.

In die Template-Datei fügen Sie das komplette Grundgerüst einer HTML-Seite ein. Im Kopf der Seite integrieren Sie die Javascript-Bibliotheken von Rails. In diesen Bibliotheken steckt der Ajax-Code.


<%= javascript_include_tag :defaults %>

Ruby-Code wird in den Templates immer in spitzen Klammern und Prozentzeichen eingefügt. Mit diesen Platzhaltern können Sie auch Werte und Variablen beispielsweise aus dem Controller einfügen. Das HTML-Gerüst der Suchseite besteht aus einem Textfeld mit Beschriftung und einem div-Block für das Suchergebnis. Das Textfeld wird mit der Methode text_field_tag() integriert. Als Wert erhält sie hier den Namen des Textfelds:



<%= text_field_tag :eingabe %>

Die Suchergebnisse landen in einem div-Block, der mit einer ID identifiziert wird. Ein zu Anfang ausgeblendetes span-Element präsentiert eine Anzeige, dass die Seite gerade geladen wird:

Ergebnisse

Nun fehlt noch die Formatierung. Sie wird mit CSS erledigt. Der Ergebnisbereich erhält eine Hintergrundfarbe und wird anfangs ausgeblendet:

#ergebnisse {
background-color: #eeeeee;
padding: 20px;
padding-bottom: 10px;
margin-top: 20px;
display: none;
}

Die einzelnen Suchergebnisse landen in untergeordneten span-Blöcken, die eine separate Formatierung erhalten:

#ergebnisse span {
background-color: #aaaaaa;
border: solid black 1px;
display: block;
padding: 5px;
margin-bottom: 10px;
}

Ajax-Aufruf

Ruby on Rails & Ajax

Die übrigen Formate dienen nur optischen Zwecken. In Sachen Logik ist nun vor allem die Ajax-Funktionalität notwendig. Hier spielt Ruby on Rails seine Stärken aus: Mit der Methode observe_field() erzeugen Sie einen automatisch in regelmäßigen Abständen ausgeführten Ajax-Aufruf. Sie müssen nur als Parameter angeben, welches Feld überwacht wird, in welchem Intervall die Überwachung ausgeführt wird (frequency) und was geschehen soll.

Die Anweisung :update gibt die ID eines Bereichs an, der beim Aufruf aktualisiert werden soll. In diesem Fall ist das der Ergebnisbereich. :url enthält den Aufruf an eine bestimmte Aktion. Hier können Sie zusätzlich beispielsweise noch einen Controller angeben. :with gibt dem Aufruf einen Parameter mit, der den Wert des Textfelds enthält. Mit :loading und :loaded fügt Rails automatisch Javascript-Code hinzu, der ausgeführt wird, wenn die Ergebnisse geladen werden beziehungsweise fertig geladen sind. Im Beispiel nutzen Sie dies, um den Ergebnisbereich und den span-Block mit der Ladeanzeige einzublenden:


<%= observe_field(:eingabe,
:frequency => 0.25,
:update => :ergebnisse,
:url => { :action => :suchergebnis },
:with => "'name=' + escape(value)",
:loading => "document.getElementById('ergebnisse').style.display=
'block';
document.getElementById('laedt').style.display='inline'",
:loaded => "document.getElementById('ergebnisse').style.display=
'block';document.getElementById('laedt').style.display='none'")
%>

Such-Controller

Ruby on Rails & Ajax

Nun folgt noch die Suchlogik. Sie wird im Controller Suche hinzugefügt. Öffnen Sie dazu die Datei app/controller/suche_controller.rb in einem Editor. Bei der einfachen Liste haben Sie mit scaffold :list eine komplette Anwendung erzeugt. Dieses Mal ist Code notwendig.

Zuerst erstellen Sie die Aktion suchergebnis, die von observe_field aufgerufen wurde. Dies funktioniert mit dem Schlüsselwort def. Darin wird überprüft, ob der Parameter name vorhanden und nicht leer ist. Ist das der Fall, dann hilft die Methode find() dabei, passende Suchergebnisse zu finden.


elemente = List.find(:all,
:conditions => [ 'name LIKE ?',
'%' + params[:name] + '%' ])

Basis der Abfrage ist das Model List und damit direkt die Datenbanktabelle lists. Mit dem Wert :all werden alle Ergebnisse zurückgeliefert. Die Abfrage wird mittels :conditions auf Werte eingeschränkt, die den als Parameter übergebenen Namen enthalten. Die Variable ausgabe nimmt den HTML-Code auf, der als Rückgabe der Suche generiert wird. In einer Schleife gehen Sie die gefundenen Kontakte durch und lesen einzelne Werte aus. Der Zugriff erfolgt dabei strikt objektorientiert über die Eigenschaft des Kontakts (hier in der Variablen person gespeichert). Mit render_text ausgabe wird dann zu guter Letzt der gesamte HTML-Code ausgegeben.

Aufrufen können Sie die Suche nun über http://localhost:3000/suche/suche/. Der Name setzt sich zusammen aus dem Controller-Namen und dem Namen für die Aktion. Wenn Sie die Suche in den Controller List integriert haben, erreichen Sie sie über http://localhost:3000/list/suche/. Alternativ zum direkten Rendern der HTML-Ausgabe könnten Sie übrigens noch eine weitere View anlegen und dort im HTML-Template die Ausgabe über Platzhalter vornehmen.

Fazit

Ruby on Rails & Ajax

Hat sich der Entwickler mit dem etwas ungewöhnlichen Konzept von Ruby on Rails bekannt gemacht, sind viele Arbeitsschritte wirklich einfach. Dieses Beispiel hat gezeigt, dass unter anderem die mitgelieferte Ajax-Bibliothek das Entwicklerleben deutlich erleichtern kann. Sie sollten allerdings nicht vergessen, dass sowohl Rails als auch Ruby als Sprache am Anfang einiges an Umdenken und Einlernaufwand erfordern. Und auch später ist das MVC-Korsett unter Umständen zu eng.

Lesen Sie auch :