#149 Rails Engines
- Download:
- source codeProject Files in Zip (203 KB)
- mp4Full Size H.264 Video (12.5 MB)
- m4vSmaller H.264 Video (8.73 MB)
- webmFull Size VP8 Video (23.1 MB)
- ogvFull Size Theora Video (17.5 MB)
Eine Rails Engine ("Schienenmotor") ist eine Möglichkeit, eine Rails-Applikation in eine andere einzubetten. Engines gibt es schon eine Weile als Plugin, aber viel der Funktionalität ist in Rails 2.3 schon eingebaut. In dieser Episode zeigen wir, wie es funktioniert.
Wir starten mit zwei separaten Applikationen. Die eine ist eine einfache e-commerce-Applikation, welche Produkte verkauft.
Unsere Shop-Applikation läuft auf Port 3000.
Die andere ist eine Blog-Applikation, welche Artikel beinhaltet und Benutzern erlaubt, diese zu kommentieren.
Unsere Blog-Applikation auf Port 3001.
Was wir erreichen möchten ist, die Blog-Funktionalität zu dem Shop hinzufügen, sodass dieser sein eigenen Blog hat. Wir könnten diese zwei Applikationen zusammenführen, aber wir wollen beide Applikationen so getrennt wie möglich halten, damit wir den Blog auch in anderen Applikationen nutzen können. Um dies zu erreichen, betten wir die Blog-Applikation mittels Engines in unseren Shop ein.
Ein Plugin erstellen
Beide Applikationen sitzen derzeit in verschiedenen Verzeichnissen. Um die Blog-App einzustöpseln, müssen wir zuerst ein Plugin in der Shop-App generieren.
``` terminal script/generate plugin blogify<p>Nachdem wir das Plugin generiert haben, erstellt es einige Dateien im <code>/vendor/plugins/blogify</code> Verzeichnis und es ist dieses Verzeichnis, in welches wir die Dateien unserer Blog-App kopieren. Das erste Verzeichnis, welches wir rüberkopieren müssen, ist <code>/app</code>.</p> ``` terminal cp -R ~/rails/blogify/app .
Jetzt haben wir alle unsere Blog-Model, -Controller und Views in dem Plugin-Verzeichnis. Diese Verzeichnisse werden automatisch von der Applikation eingebunden, sodass wir nun in der Lage sind, die Artikel- und Comments-Controller zu verwenden.
Wir müssen auch die routes-Datei der Blog-App kopieren. Wir können ein config
-Verzeichnis in dem Plugin-Verzeichnis erzeugen und die Dateien rüberkopieren.
<p>Nachdem wir die Blog-Routen kopiert haben, müssen wir die <code>map.root</code>-Zeile aus der Datei entfernen, damit es keinen Konflikt mit dem root-Controller der Shop-App gibt.</p> <h3>Die Migrationen migrieren</h3> <p>Wenn wir den Server nun starten und versuchen, den Artikel-Controller zu benutzen, bekommen wir ein Response, was bedeutet, dass Rails zwar den Controller im Plugin-Verzeichnis findet. Auf der Artikel-Seite tritt aber ein Fehler auf. Der Grund dafür sind die Datenbank-Tabellen, welche im Blog existieren, aber noch nicht in der Shop-Applikation erstellt wurden. Wir werden die Migrationen der Blog-Applikation auf der Shop-Datenbank ausführen müssen. Dazu müssen wir ein <code>db</code>-Verzeichnis in dem Plugin-Verzeichnis anlegen und unsere Migrationen rüberkopieren.</p> ``` terminal mkdir db cp -R ~/rails/blogify/db/migrate db
Obwohl die Dateien nun im richtigen Verzeichnis des Plugins sind, weiß Rails 2.3 nicht, dass es in diesem Verzeichnis danach suchen soll. Es gibt keine einfache Methode, Rails zu zeigen, wo es nachschauen soll. Also werden wir ein Rake-Task anlegen, welcher die Plugin-Migrationen mit den Migrationen der Haupt-Applikation synchronisiert.
Den rake-Task erstellen
Im Plugin-Verzeichnis gibt es ein tasks
-Verzeichnis und darin
sollte eine Datei mit dem Namen blogify_tasks.rake
liegen. Wir
werden unseren rake-Task in dieser Datei erzeugen.
<p>Unser neuer rake-Task wird <code>rsync</code> benutzen, um die Migration-Dateien zu syncen (Leider funktioniert <code>rsync</code> nicht unter Windows)</p> <p>Unseren neuen rake-Task können wir nun im Shop-Verzeichnis ausführen und die Migrationen synchronisieren</p> ``` terminal rake blogify:sync (in /Users/eifion/rails/apps_for_asciicasts/ep149) building file list ... done migrate/20090226195405_create_articles.rb migrate/20090226200008_create_comments.rb migrate/20090226202713_add_article_id_to_comments.rb sent 944 bytes received 86 bytes 2060.00 bytes/sec total size is 646 speedup is 0.63
Jedes mal, wenn wir nun unser plugin modifizieren, können wir unseren
rake-Task ausführen. Natürlich müssen wir danach rake db:migrate
ausführen um die Datenbank upzugraden.
Erfolg!
Jetzt, da die Datenbank migriert ist, können wir den Server der Applikation wieder starten. Mit den neuen Tabellen an der richtigen Stelle funktioniert der Artikel-Index jetzt, obwohl natürlich keine Artikel da sind, da wir gerade neue, leere Tabellen erstellt haben.
Stylesheets und Layouts
Der Blog-Bereich unserer Applikation funktioniert jetzt, aber er hat die
Layout-Datei und die Stylesheets unserer Shop-App angenommen. Der Grund dafür
ist, dass wir zwei Layout-Dateien mit den gleichen Namen
application.html.erb
haben, und eine Layout-Datei in der
Haupt-Applikation hat Vorrang vor einer mit dem gleichen Namen in einem Plugin.
Deshalb wird ein Template des Blog-Plugins mit der Layoutdatei des Shops
angezeigt. Dieses Verhalten wirkt auch bei Models und Controllern, was uns
erlaubt, beliebige Teile eines Plugins zu überschreiben. Da wir für unseren
Blog das gleiche Aussehen wie für den Shop haben wollen, bleiben wir bei
dieser Variante.
Was aber, wenn wir eine separate Layoutedatei und separate Stylesheets für unseren Blog haben wollen? Episode 7 behandelte verschiedene Typen von verfügbaren Layouts. Eines davon ist ein Controller-spezifisches Layout und dies ist für uns eine ideale Möglichkeit ein separates Layout für unseren Blog zu behalten, da unsere Blog-Applikation nur ein Controller hat.
Man benötigt nur zwei Schritte ein separates Layout anzulegen. Als Erstes
müssen wir die Layout-Datei des Plugins von application.html.erb
zu articles.html.erb
umbenennen.
Controller-Layouts haben Vorrang vor Applikations-Layouts, also müsste unser
Blog dieses Layout nun verwenden. Als Zweites müssen wir den Blog-Stylesheet
von der originalen Blog-App zum Stylesheet-Ordner der Shop-App kopieren. (Wir
können es nicht in ein public/stylesheets
-Verzeichnis im Plugin-Ordner
kopieren, da Rails dort nicht danach suchen wird).
Bilder und JavaScript
Egal ob wir eine separates Layout verwenden oder nicht, wollen wir
normalerweise auch andere statische Inhalte rüberkopieren, zum Beispiel Bilder
und JavaScript-Dateien. Dies können wir machen, indem wir diese Dateien von
dem public
-Verzeichnis unserer Blog-App in ein
public
-Verzeichnis des Plugins
kopieren. Um diese dann aktuell zu halten, können wir den rake-Task erweitern,
den wir früher angelegt hatten. Wenn wir, wie oben beschrieben, einen
separates Stylesheet benutzen, kann diese Technik benutzt werden, um diesen
auch zu syncen.
Der verbesserte rake-Task kopiert nun auch den public-Ordner.
Das ist erstmal alles wichtige über Rails-Engines. Auch wenn sie nicht passend für jede Rails-Applikation sind, bieten sie einen mächtigen Weg, eine Rails-Applikation in eine andere einzubetten.