Ruby Version Manager und Vim


Und noch einer. Wenn man mehr als eine Ruby-Umgebung braucht, führt kein Weg am RVM vorbei. Wozu man mehr als eine Ruby-Umgebung brauchen sollte?

Fluch und Segen in Ruby ist es meiner Ansicht nach, dass sich alles so rasend schnell weiter entwickelt (und nicht nur meiner Ansicht nach, wie ich heute in einem Gespräch mit einem Kommilitonen erfahren habe, bei dessen Arbeitsplatz man aus diesem Grunde wieder von Ruby weg möchte). Gerade über das Pakete-System RubyGems gibt es viele Plugins und Libraries, die von so vielen unterschiedlichen Teams und so sind schier unendliche Kombinationen von Gems und Versionen möglich. Dabei sind folgende Punkte problematisch:

  1. Gems für verschiedene Projekte können in unterschiedliche Versionen haben, und Kombinationen unterschiedlicher Gems in unterschiedlichen Versionen können zu Konflikten führen.
  2. Ruby ist nicht Abwärtskompatibel. Ein Upgrade des von Ruby führt meist ein erzwungenes Upgrad der Applikationen mit sich (ungünstig).
  3. Besonders stark ist Rails von der Ruby-Version abhängig und ebenfalls nicht abwärtskompatibel (ebenfalls ungünstig).

Was also tun, wenn man an zwei oder mehr unterschiedlichen Projekten mitarbeitet, die auf unterschiedliche Versionen setzten? Für OS X kommt noch eine weitere Schwierigkeit hinzu – hier ist Ruby standardmäßig installiert, da OS X selbst an einigen stellen Ruby-Code einsetzt – das kann nicht einfach auf eine neue Version gehoben werden.

Hier kommt RVM ins Spiel. Ich weiß übrigens leider nicht, wie das mit einer Windows-Version/Kompatibilität aussieht, aber ich kann mir nicht vorstellen, dass es sie gibt, da schon der Installationsprozess über die Konsole läuft. Eventuell mit Cygwin. Ansonsten: Wechselt halt auf ein besseres Betriebssystem 😛.

Über einen Einzeiler ist RVM installiert:

curl -L https://get.rvm.io | bash -s stable --rails --autolibs=enabled

Über

 rvm list known

lassen sich verschiedene Ruby-Versionen und sogar unterschiedlichste Ruby-Implementationen anzeigen und per

rvm install

installieren, und mittels

rvm use

lässt sich zwischen den installierten Versionen wechseln. Welche noch installiert sind? Das zeigt uns

rvm list

Seine wahre Mächtigkeit entfaltet RVM aber über das von ihm eingeführte Konzept der Gemsets. Gemsets sind benannte Mengen von Gems, die zusammen installiert werden. Darüber lassen sich unterschiedliche Gems kombinieren, und per Konsolenbefehle aktivieren:

rvm gemset create
rvm gemset list
rvm gemset use

Nun kann ich in diesem Gemset beliebige Gems installieren, und in einem anderen entweder eine andere Kombination oder andere Versionen der gleichen Gems.

pygospa@lalaith ~ % rvm gemset use socha
Using ruby-1.8.7-p371 with gemset socha
pygospa@lalaith ~ % rails --version
Rails 2.3.17
pygospa@lalaith ~ % rvm gemset use studCTRL
Using ruby-1.9.3-p392 with gemset studCTRL
pygospa@lalaith ~ % rails --version
Rails 3.2.13

Und last but not least, ein ganz besonderes Schmankerl: rvm ersetzt den typischen Shell-Befehl “cd“. Die Version von RVM macht bei einem Verzeichniswechsel folgendes: Sie prüft, ob in dem Verzeichnis eine .rvmrc ist. Findet es diese, dann sucht es dort nach einer Ruby-Version und einem Gemset, und voila – die aktuell benutzte Version wird für das Verzeichnis und alle Unterverzeichnisse gewechselt. Verlässt man das Verzeichnis wieder, stellt sich automatisch die Standardversion von Ruby ein. Man muss sich folglich also bei einmal anständig angelegten .rvmrc Dateien in allen seinen Projektordnern keine Gedanken mehr um die Ruby-Version machen. RVM kümmert sich um alles. Das ist sehr fein:

pygospa@lalaith ~ % ruby --version
ruby 1.9.3p392 (2013-02-22 revision 39386) [x86_64-darwin12.3.0]
pygospa@lalaith ~ % cd work/cau
pygospa@lalaith ~/work/cau % ruby --version
ruby 1.8.7 (2012-10-12 patchlevel 371) [i686-darwin12.3.0]

Eine Beispiel .rvmrc sieht dann so aus

pygospa@lalaith ~/work/cau % cat .rvmrc
rvm 1.8.7@socha

In der Regel also ein Einzeiler, der mit rvm beginnt, dann die zu verwendende Ruby-Version bezeichnet, und mit einem @ noch den Namen des Gemsets anhängt.

Es gibt aber einen Haken. Wenn ich mit Vim programmiere benutze ich gerne die Möglichkeiten, direkt in Vim Befehle an die Shell zu schicken, oder aber aus vim heraus eine Shell zu starten, wenn ich wenige Befehle eingeben muss, bevor ich wieder zurück zum Editor wechsele – das geht bequemer, als wenn ich per GNU Screen auf einen anderen Tab wechseln muss, oder dies gar über den Terminalemulator mache.

Vim aber kümmert sich allerdings nicht um eine etwa vorhandene .rvmrc, die sich da irgendwo in einem der Oberverzeichnisse befindet, aus dem heraus es gestartet wurde, wenn es danach eine eigene Shell öffnet! Daher war es trotzdem nötig, für bestimmte befehle doch mal im Screen zu springen. Lange Zeit habe ich das so hingenommen – fast zwei Jahre arbeite ich für die Software-Challenge, und immer habe ich alle Rails-Verbunden Befehle in einem extra Fenster abgeschickt, und über vim nur die Git-Kommandos losgeschickt. Nach dem ich das Wochenende aber fast non-stop an einem eigenen Projekt gearbeitet hatte, hat mich das doch irgendwie gewurmt, und daher hab ich jetzt mal geschaut, ob es eine Lösung für dieses Problem gibt. Und natürlich gibt es diese. Im freundlichen IRCChannel #rvm auf freenode wurde mir sofort geantwortet, und mir gesagt, ich solle mich mal auf die Suche des rvm-Plugin von tpope (dem bekannten Vim-Entwickler Tim Pope) machen.

Dieses ist, wenn man Pathogene benutzt (übrigens ebenfalls ein Kind von Tim Pope, und ich kann es nur jeden wärmstens empfehlen, der Vim nutzt. Glaubt mir!) rasend schnell installiert. Einfach

cd ~/.vim/bundle
git clone git://github.com/tpope/vim-rvm.git

ausführen und das Tool läuft. In der Theorie. In der Praxis muss man, wenn man zufälligerweise sowohl OS X als auch die Z-Shell nutzt (kommt leider garnicht so häufig vor, dabei ist zsh die Shell schlechtweg), noch wissen, dass man vorher seine globale zshenv nach zshrc verschieben sollte (hat mir bestimmt eine verärgerte halbe Stunde gebracht, bis ich dann gesehen hab, dass es der einzige FAQ-Punkt in der Doku ist -.- ):

sudo mv /etc/zshenv /etc/zshrc

Jetzt kann man mittels

:Rvm use <Version>

die Version angeben, die aus Vim heraus in den Shellbefehlen genutzt werden soll. Alternativ bekommt man über

:Rvm use

vim dazu veranlassen, vom Verzeichnis der Datei des aktuellen Buffer-Inhaltes ausgehend, rekursiv nach oben zu wandern, auf der Suche nach einer .rvmrc, über welche vim dann automatisch die in der .rvmrc definierte Version von Ruby und dem Gemset auswählt.

Und wem das zu viel Tiparbeit ist, der kann entweder bei jedem Start von Vim

:autocmd BufEnter * Rvm

eingeben, womit Vim angehalten wird, bei jedem Bufferwechsel erneut nach der .rvmrc für die Datei des neuen Buffers zu suchen. Alternativ trägt man sich die Zeile ohne doppelpunkt in die ~/.vimrc, und hat dies dann als Standardverhalten von vi. Einfach nur herrlich 🙂

Advertisements

Please comment. I really enjoy your thoughts!

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s