Posts Tagged ‘Rails’

Charts und Diagramme mit der Google-API in Rails erzeugen

Mittwoch, Mai 21st, 2008

Herzlich Willkommen zum ersten Artikel in meiner neuen Kategorie “Gem Review” :-)

Vor einen halben Jahr wurde von Google die Google Chart API veröffentlicht. Völlig unkompliziert, ohne Anmeldung, API-Keys oder weitere Einschränkungen können dort schicke Diagramme erzeugt werden. Alle notwendigen Parameter werden mit der Bild-URL übergeben.

Damit genug Datenpunkte zum Erstellen eines Diagramms in die URL passen, verwendet die API eine ungewöhnliche Kodierung der Zahlen aus Buchstaben und Sonderzeichen.

Um sich darüber nicht den Kopf zerbrechen zu müssen, gibt es zwei Gem-Lösungen für Ruby: gchartrb und googlecharts. Ich habe zwar zuerst den Blog-Beintrag über gchartrb gefunden, bin dann aber über den Kommentar dort zu einem Blog-Beitrag über googlecharts gekommen, welcher mich mehr angesprochen hat. U.a. deshalb weil mir dort direkt ein Beispielcode entgegensprang.

Im Moment gibt es wohl das bestreben, die beiden Projekte zu vereinen unter gchart, welches allerdings erst mit Version 0.5 angegeben wird. Ich verwende daher erstmal das googlecharts-Gem.

Installation

Installiert wird das gem durch Eingabe von
gem install googlecharts
Rails-Projekte, die dieses Gem verwenden, sollten in config/environment.rb noch die Zeile

gem 'googlecharts'

hinzufügen- damit wird erreicht, dass die Anwendung nicht startet, sollte das Gem nicht installiert sein.

In jedem Controller, dessen Views googlechart benutzen, sollte require ‘gchart’ eingefügt werden. Falls diese Charts sowieso von fast jedem View benutzt werden, kann man das require auch in application.rb (ApplicationController) einfügen, dann ist es überall geladen.

Plugin: “Micro-CMS” mit comatose

Donnerstag, April 3rd, 2008

Jede Webanwendung benötigt eigentlich ein Content-Management-System (CMS). Es gibt immer Unterseiten wie das Impressum, die AGBs oder Hilfetexte, deren Inhalt man ab und zu aktualisieren muss. Diese Texte statisch im entsprechenden View einzubinden ist schlechter Stil und erschwert die Wartung.

comatose ist ein Plugin, welches ein kleines CMS implementiert. Man kann Texte in der Datenbank ablegen und darauf mit render zugreifen, als ob man ein Partial rendern würde. Das Plugin erzeugt auch gleich das Backend zum verändern der Texte und liefert hilfreiche Rake-Tasks zum synchronisieren des Contents zwischen Development und Production-Umgebung mit.

Installation

Die Installation läuft nicht besonders anders ab als bei anderen Plugins auch. Der aktuelle Code des Comatose-Projekts ist von Rubyforge zu Google-Code umgezogen. Man installiert es aus den aktuellen Quellen mit

ruby script/plugin install http://comatose-plugin.googlecode.com/svn/trunk/comatose

Der Installationsprozess schließt mit dem Hinweis, was als nächstes zu tun ist:

ruby script/generate comatose_migration

um eine Migration zu erzeugen, die die Tabellen für das CMS initialisiert. Diese muss anschließend mit

rake db:migrate

ausgeführt werden.
Fast geschafft! Jetzt noch in der routes.rb folgende Zeilen hinzufügen (comatose_root muss in die letzte Zeile der routes.rb):

map.comatose_admin
map.comatose_root ''

Falls eine URL aufgerufen wird, die von keiner anderen Route erkannt wurde (z.B. www.beispiel.de/impressum) greift die comatose_root-Route und sucht die Comatose-Seite mit dem Namen “Impressum” heraus und zeigt sie an.

Achtung! Damit die Einträge in der routes.rb so funktionieren, muss unbedingt (auch in Development-Umgebung) der Server neu gestartet werden. Für Rails 2.0+ muss außerdem (vor Serverneustart) die Plugins acts_as_list und acts_as_tree installiert werden (ruby script/plugin install acts_as_list), andernfalls schlägt man sich mit Meldungen wie

undefined method `acts_as_tree' for #<Class:0x376faf4>

herum.

Sinnvolle Konfiguration

In der environment.rb sollte unbedingt folgender Konfigurations-Block eingefügt werden:

Comatose.configure do |config|
config.helpers << ApplicationHelper  # Falls das restful_authentication-Plugin benutzt wird
# wird der Autor einer CMS-Seite anhand des Usernamens gespeichert.
config.admin_includes << :authenticated_system
config.admin_get_author do
current_user.login
end  # Application-Helper im comatose-Controller verfügbar machen
config.helpers << ApplicationHelper

# Falls restful_authentication-Plugin benutzt wird,

# kann so der Zugriff auf das CMS auf angemeldete Benutzer beschränkt werden  config.includes << :authenticated_system
config.authorization        = Proc.new { true }
config.admin_authorization  = :login_required

# Fragment-Caching erstmal ausschalten.

config.disable_caching = true

end

Das wichtigste ist natürlich, den Zugriff auf den Admin-Bereich einzuschränken, da ansonsten jeder Besucher der Website den Inhalt verändern kann! :login_required ist eine Methode des restful_authentication-Plugins und sollte je nach Seite mit einer eigenen Methode ergänzt werden, die nur Admin-User erlaubt.

Zweiter wichtiger Punkt ist das abschalten des Fragment-Cachings. In der Production-Umgebung ist es sonst aktiviert, funktioniert aber nicht richtig- beim Fragment-Caching speichert Rails die Ausgabe von Partials, wozu aber erstmal ein geeigneter Speicherplatz organisiert werden muss (/tmp-Ordner, etc.). Zum ausprobieren des Plugins ist es daher sinnvoll diese Funktion abzuschalten. (Tuning-Maßnahmen wie Caching erschweren das Debugging und sollten erst eingebaut werden, wenn die Performance wirklich am Limit ist).

Neustart des Servers nicht vergessen- und schon kann es losgehen.

Benutzung

Unter der URL /comatose_admin ist jetzt die Admin-Oberfläche des CMS verfügbar. Die Benutzung sollte eigentlich selbsterklärend sein. Artikel können geschachtelt in einer Baumstruktur angelegt werden. Der Zugriff auf die einzelnen Artikel erfolgt über den Titel bzw. den Pfad der Titel. Für die Ausgabe stehen verschiedene Parser zur Verfügung, so dass man der Inhalt nicht unbedingt HTML sein muss. RedCloth ermöglicht z.B. das formatieren von Fettdruck, Überschriften usw. ohne HTML-Tags.

Um eine Seite aus dem Comatose-CMS anzuzeigen, kann man innerhalb der Template einfach

<%= render :comatose=> 'pfad/name' %>

aufrufen, wobei Pfad die Namen aller übergeordneten Seiten und Seite der Name der anzuzeigenden Seite ist (getrennt durch “/”).

Wärend die Anzeige über render für Textbausteine innerhalb einer Seite gedacht ist, können Comatose-Seiten auch einzeln angezeigt werden. Durch die Angabe von

map.comatose_root ''

in der letzten Zeile von route.rb haben wir ja schon eine Default-Route auf Comatose gesetzt. D.h. wenn die URL von keiner der anderen Routen verarbeitet werden kann, wird sie als Comatose-Pfadangabe behandelt. Die Idee scheint logisch, in der Praxis habe ich das aber nicht zum laufen bekommen. Zunächst mal wird bei diesen Seiten nicht das Default-Layout benutzt, was man aber durch die zusätzliche Angabe von :layout => ‘application’ ändern kann. Das zweite Problem ist, dass die View-Helper nicht geladen werden. Ich verwende beispielsweise einige Helper um Menüs (Tabs, etc.) darzustellen, was bei einer Comatose-Seite nicht funktioniert.

Aus Kommentaren des Comatose-Wiki habe ich den Trick, die Helperklassen per confg.include zuzuweisen (siehe Konfigurationsabschnitt oben), was aber bei mir aber nicht funktioniert hat.

Letztendlich habe ich einfach eine spezielle “Page”-Action in einem Controller erzeugt, dessen Template nur

<%= render :comatose=> params[:path].join('/') %>

enthält. Der letzte Eintrag in der Routes.rb lautet dann

map.cms '*path', :controller => 'home', :action => 'page'

Die spezielle Anweisung *path enthält die URI-Bestandteile als Array (daher muss weiter oben per join(’/') wieder der ursprüngliche Pfad rekonstruiert werden).

Weitere Funktionen

Im Content der Seiten kann man auch auf Ruby-Variablen zugreifen. Das ist sehr praktisch um den Content anzupassen, z.B. durch aktuelle Statistiken, das Datum oder den Benutzernamen. Ähnlich wie bei einem Partial muss dabei die Variable dem Render-Aufruf übergeben werden, z.B. so:

<%= render :comatose=>'welcome', :locals=>{ :username=>'USERNAME' } %>

In der Content-Seite mit der Überschrift ‘welcome’ kann dann so auf die Variable zugegriffen werden:

Hallo {{ username }}!

Komplexere Anweisungen sind mit sogenannten “Drops” möglich: Einem Drop kann man Codeblöcke zuweisen, die dann innerhalb der Comatose-Seite aufgerufen werden können. Die Templatesprache von Comatose ermöglicht dabei auch for-in-Konstruktionen etc.
Weiteres dazu gibt aus auf den Wiki-Seiten des Comatose-Projekts

Bewertung

****. (4/5 Sternen)

Positiv: Nützliches Plugin, großer Funktionsumfang, elegante Einbindung in Rails (render :comatose, rake-Tasks)

Negativ: Für viele Anwendungen überdimensioniert, Benutzung von zahlreichen Plugins, die zusätzlich Speicher benötigen. Standard-Konfiguration läuft nicht fehlerfrei in Production-Umgebung (wenn Fragment-Caching nicht konfiguriert wurde).

Fazit

Es handelt sich um ein nützliches und sehr leistungsfähiges Plugin. Meine anfängliche Begeisterung hat sich aber gelegt, da für viele Seiten dieser immense Funktionsumfang nicht benötigt wird. Diese Komplexität führt zu einigen Fallstricken bei der Installation und Konfiguration, die das direkte Loslegen mit dem Plugin erschweren.

Viele Seiten kommen sicher ohne Versionsmanagement und Baumstrukturen der Seiten aus, so dass man sich die Verwendung von acts_as_tree und acts_as_versioned und somit wertvollen RAM sparen könnte. Auch werden mehrere Markup-Parser geladen (RedCloth, Liquid), die nicht jeder verwenden möchte.

Man sollte daher prüfen, ob alle Funktionen tatsächlich benötigt werden. Bei einigen meiner Projekte werden ich jedenfalls bei meiner eigenen, schlankeren CMS-Lösung bleiben.

AltGr-Taste im IRB von InstantRails aktivieren

Samstag, März 22nd, 2008

InstantRails ist eine einfache Möglichkeit, unter Windows Rails-Anwendungen zu Entwickeln. Ruby, Rails, Apache und MySQL sind in diesem Paket gebundelt und müssen nicht installiert werden. Das Paket kann einfach entpackt werden und man kann loslegen (der Pfad darf allerdings keine Leerzeichen enthalten).

Die Freude wärt aber nur kurz, wenn man irb bzw. die Rails-Konsole über script/console benutzen möchte.

Dort funktionert nämlich die AltGr-Taste nicht, d.h. man kann kein @, [, ], oder | eingeben. Ich hatte dieses Problem bereits früher (konnte es beheben und vergaß es) und bekam es jetzt wieder beim Umstieg auf InstantRails 2 (mit Rails 2.0.2).

Lösung:

Man muss eine .inputrc-Datei erzeugen, die AltGr-Tastenkombinationen beschreibt. Diese Datei ist bei InstantRails schon enthalten. Sie enthält folgendes

"\M-[": "["
"\M-]": "]"
"\M-{": "{"
"\M-}": "}"
"\M-\\": "\\"
"\M-|": "|"
"\M-@": "@"
"\M-~": "~"
"\M-$": "$"

Und befindet sich im Verzeichnis <InstantRails>\ruby\bin\inputrc.euro

In der Datei irb.bat im gleichen Verzeichnis muss hinter dem @ECHO OFF folgende Zeile hinzugefügt werden:

SET INPUTRC=<pfad-zur-inputrc>\.inputrc

Es gibt noch andere Lösungsvorschläge, die aber zumindest für InstantRails nicht funktionieren. Die .inputrc gehört am besten ins Homedirectory des aktuellen Benutzers, also nach c:\Dokumente und Einstellungen\<Benutzername>. Wichtig sind in diesem Fall Anführungszeichen um die Pfadangabe, da sie Leerzeichen enthält!

Falls es eine Möglichkeit gibt die inputrc.euro aus dem bin-Verzeichnis direkt (ohne Angabe des Pfades) einzubinden, lasst es mich wissen. Ich habe bei kurzem überfliegen der Umgebungsvariablen aber nichts passendes gefunden, beispielsweise eine Variable mit dem aktuellen Pfad zum InstantRails-Verzeichnis.

(Ergänzung: Selbstverständlich muss man die .inputrc nicht woanders hin kopieren sondern kann Sie direkt mit absoluter Pfadangabe aus dem bin-Verzeichnis einbinden. Da man das InstantRails-Verzeichnis aber umbenennen und umkopieren kann, und InstantRails trotzdem funktioniert, ist eine absolute Pfadangabe zu “gefährlich”)