Lektion 18 - Gib ihr dein Ruby!

Erstellt von Frithjof Fri, 22 Feb 2008 21:25:00 GMT

Peter hat ein Programm in Ruby für Livia entwickelt und möchte es ihr zum Geburtstag schenken. Livia leidet an Unpünktlichkeit. Also hat er die letzten Tage vor dem großen Fest damit verbracht, ihr eine Zeitansage in Ruby zu schreiben. Den Quellcode teilte er auf zwei Dateien auf. Nun steht er vor der Frage, wie er ihr seine kreativen Zeilen zukommen lässt. Soll er beide Dateien als Anhang an seine Glückwunsch E-Mail kleben? Soll er sie gemeinsam in eine Zipdatei packen? In dieser Lektion lernst du, wie du deine coolen Programme an andere weitergibst. Der Quellcode zu dieser Lektion befindet sich wie immer im Downloadbereich.

Peter entscheidet sich für den Standardweg, um sein Rubyprogramm als Packet für Livia verfügbar zu machen: er erstellt ein GEM (engl. Edelstein) mit Hilfe von RubyGems, dem Packetsystem für Ruby.

Mit RubyGems kann man aber nicht nur ein Packet einer Ruby Anwendung erstellen, sondern diese Packete auch auf dem lokalen Computer verwalten, d.h. neue Gems installieren, bestehende deinstallieren, nach neuen suchen oder ein existierendes Gem auf eine neue Version updaten.

Konkret gesprochen ist ein Gem eine einzige Datei, genauer eine Archivdatei, die eine oder mehrere Dateien in komprimierter Form enthält. Die Erstellung so einer Datei erfordert den RubyGems Packetmanager.

Der Befehl gem auf der Kommandozeile teilt dir leicht mit, ob RubyGems bei dir bereits verfügbar ist.


C:\entwicklung> gem

RubyGems is a sophisticated package manager for Ruby.  This is a
basic help message containing pointers to more information.

  Usage:
    gem -h/--help
    gem -v/--version
    gem command [arguments...] [options...]

  Examples:
    gem install rake
    gem list --local
    gem build package.gemspec
    gem help install

  Further help:
    gem help commands            list all 'gem' commands
    gem help examples            show some examples of usage
    gem help <COMMAND>           show help on COMMAND
                                   (e.g. 'gem help install')
  Further information:
    http://rubygems.rubyforge.org

Der Packetmanager kommt gewöhnlich mit der Installation von Ruby auf dein System. Andernfalls musst du ihn zu Fuß installieren.

Peter hat einiges zu tun. Er teilt sich die Arbeit folgendermaßen ein:

  1. Das Zeitansageprogramm entwickeln
  2. Das Programm für den Ruby GEM Packetmanager vorbereiten. Dazu wird eine bestimmte Verzeichnisstruktur wie folgt angelegt:
    • Unterverzeichnis lib mit der Datei zeitansage.rb
    • Unterverzeichnis bin mit der Datei wie_spaet (das ist eine Rubydatei, aber ohne Endung .rb)
    • README Datei anlegen, die das Programm beschreibt
    • LICENSE Datei anlegen, die die Software Lizenz zum Programm enthält
  3. Das Gem mit Hilfe des RubyGems Packetmanagers aus einer GEM-Spezifikation erzeugen
  4. Testinstallation auf seinem lokalen Computer ausprobieren

Das Zeitansageprogramm

Peters Progrämmchen ist recht einfach. Es besteht aus der Klasse Zeitansage, deren Konstruktor (Methode initialize) eine Liste mit den Anreden und ein Muster für die Ausgabe der Uhrzeit erhält.


class Zeitansage
  def initialize(anreden, zeitmuster)
    @anreden    = anreden
    @zeitmuster = zeitmuster
  end

  def es_ist
    zeit = Time.now.strftime(@zeitmuster)
    "#{anrede} #{zeit}" 
  end

  private

  def anrede
    text = "" 
    unless @anreden.nil?
      idx = zufalls_zahl(@anreden.length)
      text = @anreden[idx]
    end
    text
  end

  # Liefert keine wirkliche Zufallszahl, für diese
  # Zwecke hier ist es aber ausreichend.
  def zufalls_zahl(max)
    (max > 0) ? (Time.now.sec % max) : 0
  end
end

Peter überlegt sich ein paar Anreden, wie etwa Hallo Livia! oder Oh, meine Prinzessin!” und legt sie in einer Liste anreden ab.


anreden = [
  "Hallo Livia!", 
  "Hi Livia!",
  "Liebe Livia!",
  "Oh, meine Prinzessin!",
  "Wozu willst du das schon wieder wissen?",
  "Sollte ich dir lieber eine Armbanduhr schenken?",
  "Ich sag nichts ohne meinen Rubyinterpreter!",
]

Bei der Ausgabe der Zeit ist er weniger kreativ und wählt folgendes Muster:


muster = "Es ist %H:%M Uhr." 

Die Prozentzeichen jeweils gefolgt von einem Buchstaben sind Platzhalter, die später dann mit den entsprechenden Werten der Zeit oder Datum ersetzt werden. So wird %H durch den Wert der Stunden und %M durch den Wert der Minuten ersetzt. Es gibt noch viel mehr solche Platzhalter für Zeit und Datum.

Ein Objekt der Klasse Zeitansage wird mit der Liste der Anreden und dem Zeitausgabemuster zum Leben erweckt und schon ist das Programm wie_spaet für Livias Geburtstag fertig!


require 'zeitansage'

anreden = [
  "Hallo Livia!", 
  "Hi Livia!",
  "Liebe Livia!",
  "Oh, meine Prinzessin!",
  "Wozu willst du das schon wieder wissen?",
  "Sollte ich dir lieber eine Armbanduhr schenken?",
  "Ich sag nichts ohne meinen Rubyinterpreter!",
]

muster = "Es ist %H:%M Uhr." 

z = Zeitansage.new(anreden, muster)
puts z.es_ist

Das Programm für den Ruby GEM Packetmanager vorbereiten

Dafür legt Peter zuerst eine Verzeichnisstruktur an, wie sie der Packetmanager verlangt. Das ausführbare Programm kommt in eine endungslose Datei wie_spaet in das Unterverzeichnis bin, die Klasse Zeitansage in eine separate Datei zeitansage.rb in das Unterverzeichnis lib.

Livia wird sicher in seinem Programmcode herumstöbern. Peter entschließt sich, ihr eine README Datei zu hinterlassen, sodass sie sich leichter in den komplexen Code einarbeiten kann.


= wie_spaet -- Ein Ruby Programm zur Zeitansage

Dieses Softwarepacket enthält 'wie_spaet', ein einfaches 
Rubyprogramm, dass die aktuelle Uhrzeit ausgibt.

wie_spaet hat die folgenden Features:

* Anreden: Die Zeitansage kann mit einer Liste von Anreden initialisiert
  werden. Aus der Liste wird bei jedem Aufruf mehr oder wenig zufällig
  eine Anrede ausgewählt. 

* Zeitausgabe: Das Ausgabeformat der Zeitansage kann ein mit den
  üblichen Platzhaltern für die Zeit- und Datumswerte versehene
  Zeichenkette sein.

== Download

Die aktuelle Version von 'wie_spaet' gibt es unter

* http://www.rubykids.de

== Installation

=== GEM Installation

wie_spaet kann als GEM gedownloaded werden und wird anschließend
mit folgendem Befehl installiert (je nach Version):

   gem install wie_spaet-0.0.1.gem

== Verwendung von wie_spaet

=== Direkte Verwendung 

Ist wie_spaet installiert, kann es einfach auf der 
Kommandozeile aufgerufen werden:

  C:\> wie_spaet

Jedes Softwarepacket, das man an andere weitergeben möchte benötigt eine Lizenz, damit für alle klar ist, ob die Software frei verwendet werden darf, ob sie etwas kostet oder ob man zu jeder Verwendung den Urheber um Erlaubnis fragen oder ihm gar noch was dafür bezahlen muss.

Peter ist da sehr großzügig und möchte sein Programm natürlich als OpenSource Software zur freien Nutzung aller Welt (insbesondere Livia) zur Verfügung stellen. Er kann sich aber nicht recht entschließen, welche OpenSource Lizenz die passende ist und erfindet kurzer Hand seine eigene.


Copyright (C) 2008 Peter @ www.rubykids.de

Peter's Geburtstags-Lizenz
Version 1.0, Februar 2008

Hiermit hat jeder, der eine Kopie dieser Software erhält, die Erlaubnis, 
sie kostenfrei unter den folgenden Bedingungen uneingeschränkt zu verwenden, 
zu kopieren, zu verändern, zu veröffentlichen und weiterzugeben:

* Der obige Copyright Hinweis und diese Erlaubnis muss in allen Kopien 
  und Teilen der Software enthalten sein.
* Der Empfänger der Software ist ein Kind, oder fühlt sich wie ein Kind, 
  oder kann sich zumindest während der Verwendung der Software 
  wie ein Kind benehmen.

Die Verzeichnisstruktur sieht bisher etwa folgendermaßen aus:

GEM mit Packetmanager und Spezifikation erzeugen

Die sogenannte Spezifikation legt genau fest, welche Teile aus der oben angelegten Verzeichnisstruktur mit in das Packet übernommen werden sollen. Die Spezifikation ist gewöhnlicher Rubycode in einer Datei mit der Endung gemspec, Peter nennt sie wie_spaet.gemspec.


spec = Gem::Specification.new

spec.name         = "wie_spaet" 
spec.version      = "0.0.1" 
spec.authors      = ["rubykids"]
spec.summary      = "Sagt dir die Zeit." 
spec.homepage     = "http://www.rubykids.de/" 
spec.description  = "Waehlt zufaellig eine Anrede und sagt dir die Zeit." 
spec.files        = [ "README", "LICENSE", "bin/wie_spaet", "lib/zeitansage.rb"]
spec.executables  = ["wie_spaet"]
spec.rdoc_options = ["--charset", "UTF-8", "--line-numbers", 
                     "--inline-source", "--main", "README", "--title", 
                     "wie_spaet -- Sagt dir die Zeit!", "--all"]
spec.has_rdoc     = true
spec.extra_rdoc_files = ["README", "LICENSE", "bin/wie_spaet"]

Jede GEM-Spezifikation zu einem RubyGems Packet sieht etwa so aus. Zuerst wird ein Objekt der Klasse Gem::Specification in der Variablen spec angelegt (was die Doppelpunkte im Klassennamen bedeuten haben wir noch nicht behandelt, das kommt noch).

Dann werden einige Attribute dieses Objektes gesetzt. Es gibt zwingend notwendige Attribute wie etwa name und version und optionale. Was die Attribute genau bedeuten ist aus ihren Bezeichnungen eigentlich meistens klar. Wir können sie hier nicht im Detail besprechen. Du kannst Genaueres aber gerne in einem Rubybuch oder im Online RubyGems Manual nachlesen.

Die Datei mit der GEM-Spezifikation legt Peter ganz oben in der Verzeichnisstruktur neben LICENSE und README ab und ruft dann in diesem Verzeichnis an der Kommandozeile den Packetmanager für RubyGems auf, um endlich das Packet für den Geburtstag zu schnüren:


C:\entwicklung\lektion_18>gem build wie_spaet.gemspec
  Successfully built RubyGem
  Name: wie_spaet
  Version: 0.0.1
  File: wie_spaet-0.0.1.gem

Es entsteht eine Datei wie_spaet-0.0.1.gem. In dieser Datei schlummert sein gesamtes Rubyprogramm, für Livia.

Sobald Livia das GEM erhält, kann sie es installieren:


C:\livia\geschenke>gem install wie_spaet-0.0.1.gem
Successfully installed wie_spaet, version 0.0.1
Installing ri documentation for wie_spaet-0.0.1...
Installing RDoc documentation for wie_spaet-0.0.1...

und nachschauen, ob es wirklich installiert ist:


C:\livia\geschenke>gem list --local wie_spaet

*** LOCAL GEMS ***

wie_spaet (0.0.1)
    Sagt dir die Zeit.

und es natürlich verwenden:


C:\livia\geschenke>wie_spaet
Oh, meine Prinzessin! Es ist 23:31 Uhr.

Was mit dem GEM nach dem Installieren passiert

Bei der Installation des GEM landet das gesamte Packet im Verzeichnisbaum der Rubyinstallation im Zweig ruby\lib\ruby\gems\1.8. im Unterordner wie_spaet-0.0.1.

Zusätzlich wird für die Datei wie_spaet aus dem bin Verzeichnis eine korrespondierende, an der Kommandozeile ausführbare Datei im bin Verzeichnis der Rubyinstallation abgelegt. Diese Datei wie_spaet.cmd kann dann direkt an der Kommandozeile mit wie_spaet aufgerufen werden.

Die GEM Spezifikationsdatei wie_spaet.gemspec taucht separat im Verzeichnis ruby\lib\ruby\gems\1.8\specifications auf.

Nachdem nun Peter die Installation überprüft hat, ist er mit seinem GEM zufrieden, findet bei seiner Lieblingsfloristin gegenüber noch ein paar hübsche Blumen, kopiert sein Gem auf einen USB-Stick und versteckt ihn zusammen mit einer Grußkarte in dem Strauß. Die Angst, Livia könnte in seinem Geburtstagsgeschenk einen Bug finden, schüttelt er ab als die Haustür hinter ihm ins Schloß fällt. Wird sich Livia freuen? Na bestimmt!