README.de.rdoc in sinatra-1.3.0.e vs README.de.rdoc in sinatra-1.3.0.f
- old
+ new
@@ -94,10 +94,21 @@
get %r{/hallo/([\w]+)} do |c|
"Hallo, #{c}!"
end
+Routen-Muster können auch mit optionalen Parametern ausgestattet werden:
+
+ get '/posts.?:format?' do
+ # passt auf "GET /posts" sowie jegliche Erweiterung
+ # wie "GET /posts.json", "GET /posts.xml" etc.
+ end
+
+Anmerkung: Solange man den sog. Path Traversal Attack-Schutz nicht deaktiviert
+(siehe weiter unten), kann es sein, dass der Request-Pfad noch vor dem Abgleich
+mit den Routen modifiziert wird.
+
=== Bedingungen
An Routen können eine Vielzahl von Bedingungen angehängt werden, die erfüllt
sein müssen, damit der Block ausgeführt wird. Möglich wäre etwa eine
Einschränkung des User-Agents:
@@ -134,10 +145,29 @@
get '/auto_gewinnen' do
"Tut mir leid, verloren."
end
+Bei Bedingungen, die mehrere Werte annehmen können, sollte ein Splat verwendet
+werden:
+
+ set(:auth) do |*roles| # <- hier kommt der Splat ins Spiel
+ condition do
+ unless logged_in? && roles.any? {|role| current_user.in_role? role }
+ redirect "/login/", 303
+ end
+ end
+ end
+
+ get "/mein/account/", :auth => [:user, :admin] do
+ "Mein Account"
+ end
+
+ get "/nur/admin/", :auth => :admin do
+ "Nur Admins dürfen hier rein!"
+ end
+
=== Rückgabewerte
Durch den Rückgabewert eines Routen-Blocks wird mindestens der Response-Body
festgelegt, der an den HTTP-Client, bzw. die nächste Rack-Middleware,
weitergegeben wird. Im Normalfall handelt es sich hierbei, wie in den
@@ -163,10 +193,13 @@
end
end
get('/') { Stream.new }
+Ebenso kann die +stream+-Helfer-Methode (s.u.) verwendet werden, die Streaming
+direkt in die Route integriert.
+
=== Eigene Routen-Muster
Wie oben schon beschrieben, ist Sinatra von Haus aus mit Unterstützung für
String-Muster und Reguläre Ausdrücke zum Abgleichen von Routen ausgestattet.
Das muss aber noch nicht alles sein, es können ohne großen Aufwand eigene
@@ -208,19 +241,22 @@
end
== Statische Dateien
Statische Dateien werden aus dem <tt>./public</tt>-Ordner ausgeliefert. Es ist
-möglich, einen anderen Ort zu definieren, indem man die <tt>:public</tt>-Option
-setzt:
+möglich, einen anderen Ort zu definieren, indem man die
+<tt>:public_folder</tt>-Option setzt:
- set :public, File.dirname(__FILE__) + '/static'
+ set :public_folder, File.dirname(__FILE__) + '/static'
Zu beachten ist, dass der Ordnername public nicht Teil der URL ist. Die Datei
<tt>./public/css/style.css</tt> ist unter
<tt>http://example.com/css/style.css</tt> zu finden.
+Um den <tt>Cache-Control</tt>-Header mit Informationen zu versorgen, verwendet
+man die <tt>:static_cache_control</tt>-Einstellung (s.u.).
+
== Views/Templates
Standardmäßig wird davon ausgegangen, dass sich Templates im
<tt>./views</tt>-Ordner befinden. Es kann jedoch ein anderer Ordner festgelegt
werden:
@@ -421,13 +457,13 @@
<tt>:layout_engine</tt>-Option verwendet wird.
=== CoffeeScript Templates
Abhängigkeit:: {coffee-script}[https://github.com/josh/ruby-coffee-script]
- und eine {Möglichkeit JavaScript auszuführen}[https://github.com/sstephenson/execjs/blob/master/README.md#readme]
+ und eine {Möglichkeit JavaScript auszuführen}[https://github.com/sstephenson/execjs/blob/master/README.md#readme]
Dateierweiterungs:: <tt>.coffee</tt>
-Beispiel:: <tt>coffee :index</tt>
+Beispiel:: <tt>coffee :index</tt>
=== Eingebettete Templates
get '/' do
haml '%div.title Hallo Welt'
@@ -727,18 +763,68 @@
Vergleichbar mit +body+ lassen sich auch Status-Code und Header setzen:
get '/foo' do
status 418
headers \
- "Allow" => "BREW, POST, GET, PROPFIND, WHEN"
+ "Allow" => "BREW, POST, GET, PROPFIND, WHEN",
"Refresh" => "Refresh: 20; http://www.ietf.org/rfc/rfc2324.txt"
halt "Ich bin ein Teekesselchen"
end
Genau wie bei +body+ liest ein Aufrufen von +headers+ oder +status+ ohne
Argumente den aktuellen Wert aus.
+=== Response-Streams
+
+In manchen Situationen sollen Daten bereits an den Client zurückgeschickt
+werden, bevor ein vollständiger Response bereit steht. Manchmal will man die
+Verbindung auch erst dann beenden und Daten so lange an den Client
+zurückschicken, bis er die Verbindung abbricht. Für diese Fälle gibt es die
++stream+-Helfer-Methode, die es einem erspart eigene Lösungen zu schreiben:
+
+ get '/' do
+ stream do |out|
+ out << "Das ist ja mal wieder fanta -\n"
+ sleep 0.5
+ out << " (bitte warten…) \n"
+ sleep 1
+ out << "- stisch!\n"
+ end
+ end
+
+Damit lassen sich Streaming-APIs realisieren, sog. {Server Sent Events}[http://dev.w3.org/html5/eventsource/]
+die als Basis für {WebSockets}[http://en.wikipedia.org/wiki/WebSocket] dienen.
+Ebenso können sie verwendet werden, um den Durchsatz zu erhöhen, wenn ein Teil
+der Daten von langsamen Ressourcen abhängig ist.
+
+Es ist zu beachten, dass das Verhalten beim Streaming, insbesondere die Anzahl
+nebenläufiger Anfragen, stark davon abhängt, welcher Webserver für die
+Applikation verwendet wird. Einige Server, z.B. WEBRick, unterstützen Streaming
+nicht oder nur teilweise. Sollte der Server Streaming nicht unterstützen, wird
+ein vollständiger Response-Body zurückgeschickt, sobald der an +stream+
+weitergegebene Block abgearbeitet ist.
+
+Ist der optionale Parameter +keep_open+ aktiviert, wird beim gestreamten Objekt
++close+ nicht aufgerufen und es ist einem überlassen dies an einem beliebigen
+späteren Zeitpunkt nachholen. Die Funktion ist jedoch nur bei Event-gesteuerten
+Serven wie Thin oder Rainbows möglich, andere Server werden trotzdem den Stream
+beenden:
+
+ set :server, :thin
+ connections = []
+
+ get '/' do
+ # Den Stream offen halten
+ stream(:keep_open) { |out| connections << out }
+ end
+
+ post '/' do
+ # In alle offenen Streams schreiben
+ connections.each { |out| out << params[:message] << "\n" }
+ "Nachricht verschickt"
+ end
+
=== Logger
Im Geltungsbereich eines Request stellt die +logger+ Helfer-Methode eine
+Logger+ Instanz zur Verfügung:
@@ -821,11 +907,11 @@
redirect to('/bar?summe=42')
oder eine Session verwendet werden:
- enable :session
+ enable :sessions
get '/foo' do
session[:secret] = 'foo'
redirect to('/bar')
end
@@ -858,11 +944,11 @@
before do
expires 500, :public, :must_revalidate
end
-Um alles richtig zu machen, sollten auch +etag+ und +last_modified+ verwendet
+Um alles richtig zu machen, sollten auch +etag+ oder +last_modified+ verwendet
werden. Es wird empfohlen, dass diese Helfer aufgerufen werden *bevor* die
eigentliche Arbeit anfängt, da sie sofort eine Antwort senden, wenn der
Client eine aktuelle Version im Cache vorhält:
get '/article/:id' do
@@ -876,12 +962,13 @@
{schwachen ETag}[http://de.wikipedia.org/wiki/HTTP_ETag] zu verwenden:
etag @article.sha1, :weak
Diese Helfer führen nicht das eigentliche Caching aus, sondern geben die dafür
-notwendigen Informationen an den Cache weiter. Für schnelle Cache-Lösungen
-bietet sich z.B. {rack-cache}[http://rtomayko.github.com/rack-cache/] an:
+notwendigen Informationen an den Cache weiter. Für schnelle Reverse-Proxy
+Cache-Lösungen bietet sich z.B.
+{rack-cache}[http://rtomayko.github.com/rack-cache/] an:
require "rack/cache"
require "sinatra"
use Rack::Cache
@@ -889,10 +976,13 @@
get '/' do
cache_control :public, :max_age => 36000
sleep 5
"hello"
end
+
+Um den <tt>Cache-Control</tt>-Header mit Informationen zu versorgen, verwendet
+man die <tt>:static_cache_control</tt>-Einstellung (s.u.).
=== Dateien versenden
Zum Versenden von Dateien kann die <tt>send_file</tt>-Helfer-Methode verwendet
werden:
@@ -995,10 +1085,41 @@
get '/' do
attachment "info.txt"
"Speichern!"
end
+=== Umgang mit Datum und Zeit
+
+Sinatra bietet eine <tt>time_for</tt>-Helfer-Methode, die aus einem gegebenen
+Wert ein Time-Objekt generiert. Ebenso kann sie nach +DateTime+, +Date+ und
+ähnliche Klassen konvertieren:
+
+ get '/' do
+ pass if Time.now > time_for('Dec 23, 2012')
+ "noch Zeit"
+ end
+
+Diese Methode wird intern für +expires, +last_modiefied+ und Freunde verwendet.
+Mit ein paar Handgriffen lässt sich diese Methode also in ihrem Verhalten
+erweitern, indem man +time_for+ in der eigenen Applikation überschreibt:
+
+ helpers do
+ def time_for(value)
+ case value
+ when :yesterday then Time.now - 24*60*60
+ when :tomorrow then Time.now + 24*60*60
+ else super
+ end
+ end
+ end
+
+ get '/' do
+ last_modified :yesterday
+ expires :tomorrow
+ "Hallo"
+ end
+
=== Nachschlagen von Template-Dateien
Die <tt>find_template</tt>-Helfer-Methode wird genutzt, um Template-Dateien zum
Rendern aufzufinden:
@@ -1087,105 +1208,143 @@
settings.foo? # => true
settings.foo # => 'bar'
...
end
+=== Einstellung des Angriffsschutzes
+
+Sinatra verwendet
+{Rack::Protection}[https://github.com/rkh/rack-protection#readme], um die
+Anwendung vor häufig vorkommenden Angriffen zu schützen. Diese Voreinstellung
+lässt sich selbstverständlich auch deaktivieren, z.B. um
+Geschwindigkeitsvorteile zu gewinnen:
+
+ disable :protection
+
+Um einen bestimmten Schutzmechanismus zu deaktivieren, fügt man +protection+
+einen Hash mit Optionen hinzu:
+
+ set :protection, :except => :path_traversal
+
+Neben Strings akzeptiert <tt>:except</tt> auch Arrays, um gleich mehrere
+Schutzmechanismen zu deaktivieren:
+
+ set :protections, :except => [:path_traversal, :session_hijacking]
+
=== Mögliche Einstellungen
-[absolute_redirects] Wenn ausgeschaltet, wird Sinatra relative Redirects
- zulassen. Jedoch ist Sinatra dann nicht mehr mit RFC 2616
- (HTTP 1.1) konform, das nur absolute Redirects zulässt.
+[absolute_redirects] Wenn ausgeschaltet, wird Sinatra relative Redirects
+ zulassen. Jedoch ist Sinatra dann nicht mehr mit RFC
+ 2616 (HTTP 1.1) konform, das nur absolute Redirects
+ zulässt.
+
+ Sollte eingeschaltet werden, wenn die Applikation
+ hinter einem Reverse-Proxy liegt, der nicht ordentlich
+ eingerichtet ist. Beachte, dass die
+ +url+-Helfer-Methode nach wie vor absolute URLs
+ erstellen wird, es sei denn, es wird als zweiter
+ Parameter +false+ angegeben.
+
+ Standardmäßig nicht aktiviert.
- Sollte eingeschaltet werden, wenn die Applikation hinter
- einem Reverse-Proxy liegt, der nicht ordentlich
- eingerichtet ist. Beachte, dass die +url+-Helfer-Methode
- nach wie vor absolute URLs erstellen wird, es sei denn,
- es wird als zweiter Parameter +false+ angegeben.
-
- Standardmäßig nicht aktiviert.
-
-[add_charsets] Mime-Types werden hier automatisch der Helfer-Methode
- <tt>content_type</tt> zugeordnet.
+[add_charsets] Mime-Types werden hier automatisch der Helfer-Methode
+ <tt>content_type</tt> zugeordnet.
- Es empfielt sich, Werte hinzuzufügen statt sie zu
- überschreiben:
+ Es empfielt sich, Werte hinzuzufügen statt sie zu
+ überschreiben:
- settings.add_charsets << "application/foobar"
+ settings.add_charsets << "application/foobar"
-[app_file] Hauptdatei der Applikation. Wird verwendet, um das
- Wurzel-, Inline-, View- und öffentliche Verzeichnis des
- Projekts festzustellen.
+[app_file] Hauptdatei der Applikation. Wird verwendet, um das
+ Wurzel-, Inline-, View- und öffentliche Verzeichnis des
+ Projekts festzustellen.
-[bind] IP-Address, an die gebunden wird (Standardwert: 0.0.0.0).
- Wird nur für den eingebauten Server verwendet.
+[bind] IP-Address, an die gebunden wird
+ (Standardwert: 0.0.0.0). Wird nur für den eingebauten
+ Server verwendet.
-[default_encoding] Das Encoding, falls keines angegeben wurde.
- Standardwert ist <tt>"utf-8"</tt>.
+[default_encoding] Das Encoding, falls keines angegeben wurde.
+ Standardwert ist <tt>"utf-8"</tt>.
-[dump_errors] Fehler im Log anzeigen.
+[dump_errors] Fehler im Log anzeigen.
-[environment] Momentane Umgebung. Standardmäßig auf
- <tt>content_type</tt> oder <tt>"development"</tt>
- eingestellt, soweit ersteres nicht vorhanden.
+[environment] Momentane Umgebung. Standardmäßig auf
+ <tt>content_type</tt> oder <tt>"development"</tt>
+ eingestellt, soweit ersteres nicht vorhanden.
-[logging] Den Logger verwenden.
+[logging] Den Logger verwenden.
-[lock] Jeder Request wird gelocked. Es kann nur ein Request pro
- Ruby-Prozess gleichzeitig verarbeitet werden.
+[lock] Jeder Request wird gelocked. Es kann nur ein Request
+ pro Ruby-Prozess gleichzeitig verarbeitet werden.
- Eingeschaltet, wenn die Applikation threadsicher ist.
- Standardmäßig nicht aktiviert.
+ Eingeschaltet, wenn die Applikation threadsicher ist.
+ Standardmäßig nicht aktiviert.
-[method_override] Verwende <tt>_method</tt>, um put/delete-Formulardaten in
- Browsern zu verwenden, die dies normalerweise nicht
- unterstützen.
+[method_override] Verwende <tt>_method</tt>, um put/delete-Formulardaten
+ in Browsern zu verwenden, die dies normalerweise nicht
+ unterstützen.
-[port] Port für die Applikation. Wird nur im internen Server
- verwendet.
+[port] Port für die Applikation. Wird nur im internen Server
+ verwendet.
-[prefixed_redirects] Entscheidet, ob <tt>request.script_name</tt> in Redirects
- eingefügt wird oder nicht, wenn kein absoluter Pfad
- angegeben ist. Auf diese Weise verhält sich
- <tt>redirect '/foo'</tt> so, als wäre es ein
- <tt>redirect to('/foo')</tt>.
- Standardmäßig nicht aktiviert.
+[prefixed_redirects] Entscheidet, ob <tt>request.script_name</tt> in
+ Redirects eingefügt wird oder nicht, wenn kein
+ absoluter Pfad angegeben ist. Auf diese Weise verhält
+ sich <tt>redirect '/foo'</tt> so, als wäre es ein
+ <tt>redirect to('/foo')</tt>. Standardmäßig nicht
+ aktiviert.
+
+[protection] Legt fest, ob der Schutzmechanismus für häufig
+ Vorkommende Webangriffe auf Webapplikationen aktiviert
+ wird oder nicht. Weitere Informationen im vorhergehenden
+ Abschnitt.
-[public] Das öffentliche Verzeichnis, aus dem Daten zur Verfügung
- gestellt werden können.
+[public_folder] Das öffentliche Verzeichnis, aus dem Daten zur
+ Verfügung gestellt werden können.
-[reload_templates] Im development-Modus aktiviert.
+[reload_templates] Im development-Modus aktiviert.
-[root] Wurzelverzeichnis des Projekts.
+[root] Wurzelverzeichnis des Projekts.
-[raise_errors] Einen Ausnahmezustand aufrufen. Beendet die Applikation.
+[raise_errors] Einen Ausnahmezustand aufrufen. Beendet die
+ Applikation.
-[run] Wenn aktiviert, wird Sinatra versuchen, den Webserver zu
- starten. Nicht verwenden, wenn Rackup oder anderes
- verwendet werden soll.
+[run] Wenn aktiviert, wird Sinatra versuchen, den Webserver
+ zu starten. Nicht verwenden, wenn Rackup oder anderes
+ verwendet werden soll.
-[running] Läuft der eingebaute Server? Diese Einstellung nicht
- ändern!
+[running] Läuft der eingebaute Server? Diese Einstellung nicht
+ ändern!
-[server] Server oder Liste von Servern, die als eingebaute Server
- zur Verfügung stehen.
- Standardmäßig auf ['thin', 'mongrel', 'webrick']
- voreingestellt. Die Anordnung gibt die Priorität vor.
+[server] Server oder Liste von Servern, die als eingebaute
+ Server zur Verfügung stehen.
+ Standardmäßig auf ['thin', 'mongrel', 'webrick']
+ voreingestellt. Die Anordnung gibt die Priorität vor.
-[sessions] Sessions auf Cookiebasis aktivieren.
+[sessions] Sessions auf Cookiebasis aktivieren.
-[show_exceptions] Stacktrace im Browser bei Fehlern anzeigen.
+[show_exceptions] Stacktrace im Browser bei Fehlern anzeigen.
-[static] Entscheidet, ob Sinatra statische Dateien zur Verfügung
- stellen soll oder nicht.
- Sollte nicht aktiviert werden, wenn ein Server verwendet
- wird, der dies auch selbstständig erledigen kann.
- Deaktivieren wird die Performance erhöhen.
- Standardmäßig aktiviert.
+[static] Entscheidet, ob Sinatra statische Dateien zur Verfügung
+ stellen soll oder nicht.
+ Sollte nicht aktiviert werden, wenn ein Server
+ verwendet wird, der dies auch selbstständig erledigen
+ kann. Deaktivieren wird die Performance erhöhen.
+ Standardmäßig aktiviert.
-[views] Verzeichnis der Views.
+[static_cache_control] Wenn Sinatra statische Daten zur Verfügung stellt,
+ können mit dieser Einstellung die +Cache-Control+
+ Header zu den Responses hinzugefügt werden. Die
+ Einstellung verwendet dazu die +cache_control+
+ Helfer-Methode. Standardmäßig deaktiviert.
+ Ein Array wird verwendet, um mehrere Werte gleichzeitig
+ zu übergeben:
+ <tt>set :static_cache_control, [:public, :max_age => 300]</tt>
+[views] Verzeichnis der Views.
+
== Fehlerbehandlung
Error-Handler laufen in demselben Kontext wie Routen und Filter, was bedeutet,
dass alle Goodies wie <tt>haml</tt>, <tt>erb</tt>, <tt>halt</tt>, etc.
verwendet werden können.
@@ -1499,10 +1658,11 @@
my_app = Sinatra.new { get('/') { "hallo" } }
my_app.run!
Die Applikation kann mit Hilfe eines optionalen Parameters erstellt werden:
+ # config.ru
require 'sinatra/base'
controller = Sinatra.new do
enable :logging
helpers MyHelpers
@@ -1641,55 +1801,70 @@
Die folgenden Versionen werden offiziell unterstützt:
[ Ruby 1.8.7 ]
1.8.7 wird vollständig unterstützt, aber solange nichts dagegen spricht,
wird ein Update auf 1.9.2 oder ein Umstieg auf JRuby/Rubinius empfohlen.
+ Unterstützung für 1.8.7 wird es mindestens bis Sinatra 2.0 und Ruby 2.0 geben,
+ es sei denn, dass der unwahrscheinliche Fall eintritt und 1.8.8 rauskommt. Doch
+ selbst dann ist es eher wahrscheinlich, dass 1.8.7 weiterhin unterstützt wird.
+ <b>Ruby 1.8.6 wird nicht mehr unterstützt.</b> Soll Sinatra unter 1.8.6
+ eingesetzt werden, muss Sinatra 1.2 verwendet werden, dass noch bis zum
+ Release von Sinatra 1.4.0 fortgeführt wird.
[ Ruby 1.9.2 ]
- 1.9.2 wird unterstützt und empfohlen. Beachte, dass Markaby und Radius
- momentan noch nicht kompatibel mit 1.9 sind. Version 1.9.0p0 sollte nicht
+ 1.9.2 wird voll unterstützt und empfohlen. Beachte, dass Markaby und Radius
+ momentan noch nicht kompatibel mit 1.9 sind. Version 1.9.2p0 sollte nicht
verwendet werden, da unter Sinatra immer wieder Segfaults auftreten.
+ Unterstützung wird es mindestens bis zum Release von Ruby 1.9.4/2.0 geben und
+ das letzte Sinatra Release für 1.9 wird so lange unterstützt, wie das Ruby
+ Core-Team 1.9 pflegt.
+[ Ruby 1.9.3 ]
+ Obwohl Tests bereits auf 1.9.3 laufen, sind bisher keine Applikationen auf
+ 1.9.3 in Produktion bekannt. Ebenso wie bei 1.9.2 besteht die gleiche Warnung
+ zum Patchlevel 0.
+
[ Rubinius ]
- Rubinius (rbx >= 1.2.3) wird offiziell unter Einbezug aller Templates
+ Rubinius (rbx >= 1.2.4) wird offiziell unter Einbezug aller Templates
unterstützt.
[ JRuby ]
- JRuby wird offiziell unterstützt (JRuby >= 1.6.1). Probleme mit Template-
+ JRuby wird offiziell unterstützt (JRuby >= 1.6.3). Probleme mit Template-
Bibliotheken Dritter sind nicht bekannt. Falls JRuby zum Einsatz kommt,
sollte aber darauf geachtet werden, dass ein JRuby-Rack-Handler zum Einsatz
kommt – der Thin-Web-Server wird bisher nicht unterstütz. JRubys
Unterstützung für C-Erweiterungen sind zur Zeit noch experimenteller Natur,
betrifft im Moment aber nur RDiscount und Redcarpet.
-<b>Ruby 1.8.6 wird nicht weiter unterstützt.</b> Falls Sinatra trotzdem unter
-1.8.6 eingesetzt wird, muss Sinatra 1.2 verwendet werden, dass noch bis zum
-Release von Sinatra 1.4.0 mit kleinen Bugfixes versorgt werden wird.
Weiterhin werden wir auf kommende Ruby-Versionen ein Auge haben.
Die nachfolgend aufgeführten Ruby-Implementierungen werden offiziell nicht von
Sinatra unterstützt, funktionieren aber normalerweise:
+* Ruby Enterprise Edition
* Ältere Versionen von JRuby und Rubinius
* MacRuby, Maglev, IronRuby
-* Ruby 1.9.0 und 1.9.1
+* Ruby 1.9.0 und 1.9.1 (wird jedoch nicht empfohlen, s.o.)
Nicht offiziell unterstützt bedeutet, dass wenn Sachen nicht funktionieren,
wir davon ausgehen, dass es nicht an Sinatra sondern an der jeweiligen
Implentierung liegt.
Im Rahmen unserer CI (Kontinuierlichen Integration) wird bereits ruby-head
-(das kommende Ruby 1.9.3) mit eingebunden. Da noch alles im Fluss ist, kann zur
+(das kommende Ruby 1.9.4) mit eingebunden. Da noch alles im Fluss ist, kann zur
Zeit für nichts garantiert werden. Es kann aber erwartet werden, dass Ruby
-1.9.3p0 von Sinatra unterstützt werden wird.
+1.9.4p0 von Sinatra unterstützt werden wird.
Sinatra sollte auf jedem Betriebssystem laufen, dass den gewählten Ruby-
Interpreter unterstützt.
-== Der neueste Stand (The Bleeding Edge)
+Sinatra wird aktuell nicht unter Cardinal, SmallRuby, BleuRuby oder irgendeiner
+Version von Ruby vor 1.8.7 laufen.
+== Der neuste Stand (The Bleeding Edge)
+
Um auf dem neusten Stand zu bleiben, kann der Master-Branch verwendet werden.
Er sollte recht stabil sein. Ebenso gibt es von Zeit zu Zeit prerelease Gems,
die so installiert werden:
gem install sinatra --pre
@@ -1781,5 +1956,6 @@
* {Sinatra Book Contrib}[http://sinatra-book-contrib.com/] Sinatra-Rezepte aus
der Community
* API Dokumentation für die {aktuelle Version}[http://rubydoc.info/gems/sinatra]
oder für {HEAD}[http://rubydoc.info/github/sinatra/sinatra] auf
http://rubydoc.info
+* {CI Server}[http://ci.rkh.im/view/Sinatra/]
\ No newline at end of file