Sinatra / Ruby Apps als Windows exe?

Klar, mit Ocra!

Aktuell arbeite ich an einem kleinen Tool zur Personenverwaltung. Dreh und Angelpunkt dabei ist eine gute Suche. Um die Anwendung solls hier allerdings nicht gehen. Ich wollte das Tool gern mit Ruby entwickeln, eine Anforderung ist allerdings, dass es später bei verschiedenen Personen unter Windows laufen soll. Gut, als Webapp ist das ja kein Problem, doch sollen die Personendaten nicht im Web liegen, sondern bei den jeweiligen Leuten auf dem lokalen Rechner. Daher wäre eine Windowsanwendung der bessere Weg. Also hab ich mich schlau gemacht und rausgesucht wie man Ruby-Webapps in eine .exe verwandelt.

Schlussendlich hab ich mit Ocra wunderbare Erfahrungen gemacht, die ich hier teilen möchte. Nicht zuletzt um mich selbst wieder daran zu erinnern.

Da Orca nur in einer Windows Umgebung läuft muss man entweder selbst unter Windows entwickeln oder sicherstellen, dass seine Anwendung – in meinem Fall übrigends eine Sinatra App – auch auf Windows läuft. Dank RubyInstaller ist die Installation von Ruby unter Windows ja kein Problem. Um die .exe später zu Verwenden brauch man übrigends kein installiertes Ruby mehr.

Arbeitet man mit Bundler sollten die benötigten Gems recht einfach und schnell installiert sein. Ist sichergestellt, dass deine Anwendung auf Windows funktioniert, gehts weiter.

Man installiert Ocra via ‚gem install ocra‘ und öffnet dann eine Konsole, geht ins Verzeichnis seiner Anwendung und gibt dort

ocra --no-autoload DeineAnwendung.rb views\* public\*

ein. Die Option –no-autoload verhindert, dass automatisch alle Abhängigkeiten geladen werden. Wenn ich diese Option weglasse werden unnötige Abhängigkeiten von Rack geladen und das wirft dann einen Fehler vom gem i18n. Bei Problemen wärend der Umwandlung lohnt es sich allemal mit den Parametern von Ocra rumzuexperimentieren.

Ocra startet nun deine Anwendung (in meinem Fall den Sinatra Rackserver) um die benötigten Bibliotheken und Gems zu ermitteln. Man kann Ocra auch anweisen ein Gemfile zu nutzen und die App nicht zu starten (via –no-dep-run und –gemfile ). Bei mir klappte es damit allerdings leider nicht später die exe auch zu verwenden. Mir erscheint es als würden dann nicht alle notwendigen Bibliotheken erkannt, vorallem gibt es dann Probleme mit der Rubygems Umgebung. Daher ist es besser die Anwendung von Ocra starten zu lassen und dann komplett zu testen. Bei mir bedeutet das, alle Funktionen im Browser durchzutesten. Wichtig sind dabei vorallem Datenbank Aktionen. Hab ich diese Dinge nicht getestet wurden auch entsprechende Abhängigkeiten nicht erkannt.

Anschließend kann man seine Anwendung beenden, hier z.B. mit Ctrl+c. Ocra listet nun alle Abhängigkeiten auf und erstellt die .exe.

Einige Hinweise

Dein Script sollte ganz oben ein ‚require „rubygems“‚ beinhalten, ansonsten kommt es ggf. später in der exe zu Problemen mit der Rubygems Umgebung.

Bindet man andere Rubydateien in seiner Anwendung ein, dann lohnt es sich ‚require_relative‘ zu verwenden statt mit ‚./‘ das aktuelle Verzeichnis kenntlich zu machen.

Hat man auch eine Datenbank in Form einer Datei, z.B. SQLite3, dann sollte man nach generierung der .exe die Datenbankdatei zusammen mit der .exe ausliefern. Lässt man die Datenbankdatei mit in die .exe einpacken werden später Änderungen an den Daten nicht dauerhaft gespeichert, weil die DB-Datei dann immer wieder neu ausgepackt wird und daher beim alten Stand bleibt. Bei einer MySql Datenbankverbindung o.ä. ist das natürlich egal.

Firewall: Unter Windows startet Sinatra den Server meist auf localhost:4567. Bei jedem Start erscheint dann eine Firewall Meldung. Da dies recht nervig ist habe ich den lokalen Port 4567 in die Firewall als eingehende Regel definiert. Mein Ziel ist nach erfolgreichem Start direkt den Browser zu öffnen oder eine andere Adresse zu verwenden, aber dazu folgt ggf. später ein Update.

Links zum Thema

http://rubyonwindows.blogspot.de/2009/05/ocra-one-click-ruby-application-builder.html
http://wiki.ruby-portal.de/OCRA

Advertisements

VIM Autoscroll Buffer

Die benötigten Einstellungen: scrolloff | scrolljump

Mit dieser Option kann man einstellen, wann VIM den Buffer scrollt. Gibt man beispielsweise scrolloff=5 ein, dann scrollt vim automatisch wenn man den Cursor auf der 5. Zeile vom unteren oder oberen Bildschirmrand entfernt hat. mit scrolljump stellt man ein um wieviel Zeilen dann gescrollt wird. Gibt man hier eine positive Zahl ein, dann meint das die Zeilen die gescrollt werden, bei einer negativen Zahl handelt es sich um eine Prozentangabe um die gescrollt wird.

set scrolloff=n
set scrolljump=n/-n%

Ruby require OpenSSL

Neulich war es wieder mal so weit… Ich hab eine neue Linuxkiste (xubuntu) aufgesetzt und mich häuslich eingerichtet. Dabei kam ein altbekanntes, aber auch in Vergessenheit geratenes, Problem auf: Ruby und OppenSSL

Hier zur Erinnerung wie ichs diesmal auf die Reihe bekommen hab:
– natürlich muss zuerstmal openssl installiert sein
– Nötige Bibliotheken installieren: sudo apt-get install zlib1g-dev libreadline-dev libssl-dev libcurl4-openssl-dev
– Ruby mit rbenv und openssl installieren: hierlang und hier ein Script

Zugegeben, ich hab den Artikel schon eine Weile rumliegen, daher kann ich mich an einige Details bereits nichtmehr erinnern. Wenn ich das nächste mal Probleme mit OpenSSL habe, werde ich das hier aber bei Bedarf updaten.

Quick Tip: jQuery Object im trigger übergeben

Laut der jQuery API Seite zu `trigger()` müssen die zusätzlichen Parameter als Array übergeben werden. Ab 1.6.2 kann man einen einzelnen Parameter auch ohne die Array-Notation übergeben. Leider klappt das anscheinend mit einem in jQuery gewrappten Element nicht wirklich.

$('body').bind('sampleEvent', function(e, liste) {
  console.log(liste.length);
});

var liste = $('a');
console.log(liste.length);
$('body').trigger('sampleEvent', liste);

In `liste` befinden sich mehrere Elemente (da es mehrere a-Tags auf meiner Beispielseite gab). Die Ausgabe im EventHandler gibt allerdings ‚undefined‘ zurück. Übergibt man den Parameter nun aber als Array `$(‚body‘).trigger(’sampleEvent‘, [liste]);` klappt alles wunderbar.

So ganz bin ich noch nicht dahinter gekommen woran es liegt. Wenns jemand weiß, dann würd ich mich über ein Kommentar freuen.

Quick Tip: Glow-Effekt bei aktiven Fenstern in KDE abschalten

Ich bin gerade dabei mir eine neue Virtuelle Maschine aufzusetzen. Ich habe mich für Mint 12 KDE entschieden. Bisher war ich unter xubuntu unterwegs und auch zufrieden. Jedoch gefällt mir KDE irgendwie und so hab ich mich entschlossen selbigen eine Chance zu geben.

Eine Sache viel mir gleich zu beginn auf: Das aktive Fenster erhält eine blaue Umrandung, ähnlich einem Glühen. Was ganz nett gedacht sein mag, nervte mich schon nach ein paar Minuten. Also hab ich etwas probiert und gesucht und hier ist die richtige Baustelle um den Effekt anzupassen oder – wie in meinem Fall – ganz abzustellen:

Unter
Systemeinstellungen->Erscheinungsbild der Arbeitsfläche->Fensterdekoration
auf den Knopf „Fensterdekoration einrichten“ klicken und im aufgehenden Fenster zum Reiter „Schatten“ wechseln. Auf der rechten Seite kann man den Effekt abschalten oder anpassen.

Quick Tip: Chrome Fullscreen Mode unter Mac OS X Snow Leopard

Unter Windows geht das ja ganz einfach mit F11. Mac macht das da etwas anders. Zum Beispiel kann man über das Chrome Menü (Schraubschlüssel rechts oben) neben Zoom auf das vergrößern Icon klicken. Leider findet man dann allerdings den Weg zurück nicht ganz so schnell…

Die einfacherer Lösung ist shift+cmd+f. Funktioniert sowohl zum aktivieren als auch zum deaktivieren des Fullscreen Mode.

Stasis deploy auf Apache Webserver via git hook post-receive

Ich bin gerade dabei meine Website zu überarbeiten. Bisher läuft die Seite über das PHP Framework Codeigniter, doch für 2 plain HTML Seiten und ein Kontakformular ist das im Grunde völlig überdemensioniert. Daher hab ich beschlossen alles über stink normale statische HTML Dateien abzuwickeln und das Kontaktformular durch eine virtuelle Visitenkarte zu ersetzen. Dafür hab ich mich für das RubyGem Stasis entschieden. Der Vorteil hier ist, dass ich SASS, Cofescript, HAML und Co. schreiben kann und der Stasis Interpreter mir diese in CSS, JS und HTML Dateien umwandelt. Mehr will ich dazu gar nicht sagen, außer, dass es sich bisher großartig und zweckentsprechend einsetzten lässt. Als Versionskontrolle nehme ich – wie bei allen meinen Projekten – GIT.

Stasis erzeugt ein public Verzeichnis, dass alle statischen HTML und konvertierten CSS / JS Dateien beinhaltet. Diese könnte man direkt per FTP auf einen Webhost seiner Wahl schieben und gut wärs. Da ich aber zum einen einen eigenen Server betreibe und per GIT in einem develop und einem master Branch arbeite – und auch beide Stände auf einen Server deployen möchte – ist mit der Weg über FTP zu umständlich. Von Ruby On Rails bin ich dank Capistrano ja auch schon ein wenig verwöhnt. Für die Website wollt ich es allerdings nicht über Capistrano erledigen sondern schlicht und einfach einen Git Hook einsetzen, namendlich, den Post-Receive Hook. Dazu habe ich ein bare Repo auf meinem Server. In dieses Pushe ich meinen lokalen Enwicklungsstand (das stasis Projekt, ohne das von stasis erzeugte public Verzeichnis, das ich auch nicht unter Versionskontrolle genommen habe). Auch im remote bare Repo gibt es die beiden Branches develop und master. Ich möchte das beide in ein, vom Apache erreichbares, Verzeichnis kopiert werden, sobald etwas gepushed wird.

Soweit so gut, doch die Schwierigkeit bestand für mich darin, dass in den Hooks meine RVM (Ruby Manager) Umgebung nicht richtig geladen wird (das mag auch auf eine fehlerhafte RVM Konfiguration zurückzuführen sein, die ich atm allerdings nicht beheben will und kann). Es hat mich einige Zeit gekostet, doch nun habe ich einen post-receive Hook zusammengebaut, der RVM läd (damit auch die Gems Verfügbar macht) und auch noch zwichen develop und master zu unterscheiden weiß:

# File /git-bare-repo/hooks/post-receive
#!/bin/bash

# Läd RVM in die Shell Session (Pfade kontrollieren, ggf. liegt rvm wo anders)
[[ -s "/usr/local/rvm/scripts/rvm" ]] && . "/usr/local/rvm/scripts/rvm" 

# Damit GIT_DIR und GIT_WORK_TREE zurückgesetzt werden und man sich über cd bewegen kann
unset $(git rev-parse --local-env-vars)
cd /pfad/zu/master/worktree

# Liest den branch aus
while read oldrev newrev ref
do
    branch=$ref
done

if [ "$branch" == "refs/heads/develop" ]; then
        cd /pfad/zu/develop/worktree
fi

git reset --hard
git pull origin $branch
# rendert die Files und erzeugt public/ <- ist Apache VirtualHost DocumentRoot
stasis

„/pfad/zu/master/worktree“ und „/pfad/zu/develop/worktree“ sind dabei die Verzeichnisse, unter denen per Stasis der public Ordner angelegt wird, welcher wiederrum als DocumentRoot für Apache dient.