README.de.md in sinatra-1.4.5 vs README.de.md in sinatra-1.4.6
- old
+ new
@@ -1,9 +1,9 @@
# Sinatra
*Wichtig: Dieses Dokument ist eine Übersetzung aus dem Englischen und unter
-Umständen nicht auf dem aktuellen Stand (aktuell Sinatra 1.4.2).*
+Umständen nicht auf dem aktuellen Stand (aktuell Sinatra 1.4.5).*
Sinatra ist eine
[DSL](http://de.wikipedia.org/wiki/Domänenspezifische_Sprache), die das
schnelle Erstellen von Webanwendungen in Ruby mit minimalem Aufwand
ermöglicht:
@@ -52,25 +52,28 @@
* [Less Templates](#less-templates)
* [Liquid Templates](#liquid-templates)
* [Markdown Templates](#markdown-templates)
* [Textile Templates](#textile-templates)
* [RDoc Templates](#rdoc-templates)
+ * [AsciiDoc Templates](#asciidoc-templates)
* [Radius Templates](#radius-templates)
* [Markaby Templates](#markaby-templates)
* [RABL Templates](#rabl-templates)
* [Slim Templates](#slim-templates)
* [Creole Templates](#creole-templates)
+ * [MediaWiki Templates](#mediawiki-templates)
* [CoffeeScript Templates](#coffeescript-templates)
* [Stylus Templates](#stylus-templates)
* [Yajl Templates](#yajl-templates)
* [WLang Templates](#wlang-templates)
* [Auf Variablen in Templates zugreifen](#auf-variablen-in-templates-zugreifen)
* [Templates mit `yield` und verschachtelte Layouts](#templates-mit-yield-und-verschachtelte-layouts)
* [Inline-Templates](#inline-templates)
* [Benannte Templates](#benannte-templates)
* [Dateiendungen zuordnen](#dateiendungen-zuordnen)
* [Eine eigene Template-Engine hinzufügen](#eine-eigene-template-engine-hinzufgen)
+ * [Eigene Methoden zum Aufsuchen von Templates verwenden](#eigene-methoden-zum-aufsuchen-von-templates-verwenden)
* [Filter](#filter)
* [Helfer](#helfer)
* [Sessions verwenden](#sessions-verwenden)
* [Anhalten](#anhalten)
* [Weiterspringen](#weiterspringen)
@@ -158,36 +161,36 @@
`params`-Hash zugänglich gemacht werden:
```ruby
get '/hallo/:name' do
# passt auf "GET /hallo/foo" und "GET /hallo/bar"
- # params[:name] ist dann 'foo' oder 'bar'
- "Hallo #{params[:name]}!"
+ # params['name'] ist dann 'foo' oder 'bar'
+ "Hallo #{params['name']}!"
end
```
Man kann auf diese auch mit Block-Parametern zugreifen:
```ruby
get '/hallo/:name' do |n|
- # n entspricht hier params[:name]
+ # n entspricht hier params['name']
"Hallo #{n}!"
end
```
Routen-Muster können auch mit sog. Splat- oder Wildcard-Parametern über das
-`params[:splat]`-Array angesprochen werden:
+`params['splat']`-Array angesprochen werden:
```ruby
get '/sag/*/zu/*' do
# passt z.B. auf /sag/hallo/zu/welt
- params[:splat] # => ["hallo", "welt"]
+ params['splat'] # => ["hallo", "welt"]
end
get '/download/*.*' do
# passt auf /download/pfad/zu/datei.xml
- params[:splat] # => ["pfad/zu/datei", "xml"]
+ params['splat'] # => ["pfad/zu/datei", "xml"]
end
```
Oder mit Block-Parametern:
@@ -198,12 +201,12 @@
```
Routen mit regulären Ausdrücken sind auch möglich:
```ruby
-get %r{/hallo/([\w]+)} do
- "Hallo, #{params[:captures].first}!"
+get /\A\/hallo\/([\w]+)\z/ do
+ "Hallo, #{params['captures'].first}!"
end
```
Und auch hier können Block-Parameter genutzt werden:
@@ -220,10 +223,21 @@
# passt auf "GET /posts" sowie jegliche Erweiterung
# wie "GET /posts.json", "GET /posts.xml" etc.
end
```
+Routen können auch den query-Parameter verwenden:
+
+``` ruby
+get '/posts' do
+ # matches "GET /posts?title=foo&author=bar"
+ title = params['title']
+ author = params['author']
+ # uses title and author variables; query is optional to the /posts route
+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
@@ -232,11 +246,11 @@
sein müssen, damit der Block ausgeführt wird. Möglich wäre etwa eine
Einschränkung des User-Agents über die interne Bedingung `:agent`:
```ruby
get '/foo', :agent => /Songbird (\d\.\d)[\d\/]*?/ do
- "Du verwendest Songbird Version #{params[:agent][0]}"
+ "Du verwendest Songbird Version #{params['agent'][0]}"
end
```
Wird Songbird als Browser nicht verwendet, springt Sinatra zur nächsten Route:
@@ -259,10 +273,11 @@
get '/', :provides => ['rss', 'atom', 'xml'] do
builder :feed
end
```
+`provides` durchsucht den Accept-Header der Anfrage
Eigene Bedingungen können relativ einfach hinzugefügt werden:
```ruby
set(:wahrscheinlichkeit) { |value| condition { rand <= value } }
@@ -571,11 +586,11 @@
#### Builder Templates
<table>
<tr>
<td>Abhängigkeit</td>
- <td><a href="http://builder.rubyforge.org/">builder</a></td>
+ <td><a href="https://github.com/jimweirich/builder">builder</a></td>
</tr>
<tr>
<td>Dateierweiterung</td>
<td><tt>.builder</tt></td>
</tr>
@@ -688,12 +703,12 @@
<td>Abhängigkeit</td>
<td>Eine der folgenden Bibliotheken:
<a href="https://github.com/rtomayko/rdiscount" title="RDiscount">RDiscount</a>,
<a href="https://github.com/vmg/redcarpet" title="RedCarpet">RedCarpet</a>,
<a href="http://deveiate.org/projects/BlueCloth" title="BlueCloth">BlueCloth</a>,
- <a href="http://kramdown.rubyforge.org/" title="kramdown">kramdown</a> oder
- <a href="http://maruku.rubyforge.org/" title="maruku">maruku</a>
+ <a href="http://kramdown.gettalong.org/" title="kramdown">kramdown</a> oder
+ <a href="https://github.com/bhollis/maruku" title="maruku">maruku</a>
</td>
</tr>
<tr>
<td>Dateierweiterungen</td>
<td><tt>.markdown</tt>, <tt>.mkd</tt> und <tt>.md</tt></td>
@@ -766,11 +781,11 @@
#### RDoc Templates
<table>
<tr>
<td>Abhängigkeit</td>
- <td><a href="http://rdoc.rubyforge.org/">rdoc</a></td>
+ <td><a href="http://rdoc.sourceforge.net/">rdoc</a></td>
</tr>
<tr>
<td>Dateierweiterung</td>
<td><tt>.rdoc</tt></td>
</tr>
@@ -799,16 +814,37 @@
Da man Ruby nicht von RDoc heraus aufrufen kann, können auch Layouts nicht in
RDoc geschrieben werden. Es ist aber möglich, einen Renderer für die Templates
zu verwenden und einen anderen für das Layout, indem die
`:layout_engine`-Option verwendet wird.
+#### AsciiDoc Templates
+
+<table>
+ <tr>
+ <td>Abhängigkeit</td>
+ <td><a href="http://asciidoctor.org/" title="Asciidoctor">Asciidoctor</a></td>
+ </tr>
+ <tr>
+ <td>Dateierweiterungen</td>
+ <td><tt>.asciidoc</tt>, <tt>.adoc</tt> und <tt>.ad</tt></td>
+ </tr>
+ <tr>
+ <td>Beispiel</td>
+ <td><tt>asciidoc :README, :layout_engine => :erb</tt></td>
+ </tr>
+</table>
+
+Da man aus dem AsciiDoc-Template heraus keine Ruby-Methoden aufrufen kann
+(ausgenommen `yield`), wird man üblicherweise locals verwenden wollen, mit
+denen man Variablen weitergibt.
+
#### Radius Templates
<table>
<tr>
<td>Abhängigkeit</td>
- <td><a href="http://radius.rubyforge.org/">radius</a></td>
+ <td><a href="https://github.com/jlong/radius">radius</a></td>
</tr>
<tr>
<td>Dateierweiterung</td>
<td><tt>.radius</tt></td>
</tr>
@@ -910,10 +946,48 @@
Da man Ruby nicht von Creole heraus aufrufen kann, können auch Layouts nicht in
Creole geschrieben werden. Es ist aber möglich, einen Renderer für die Templates
zu verwenden und einen anderen für das Layout, indem die `:layout_engine`-Option
verwendet wird.
+#### MediaWiki Templates
+
+<table>
+ <tr>
+ <td>Abhängigkeit</td>
+ <td><a href="https://github.com/nricciar/wikicloth" title="WikiCloth">WikiCloth</a></td>
+ </tr>
+ <tr>
+ <td>Dateierweiterungen</td>
+ <td><tt>.mediawiki</tt> und <tt>.mw</tt></td>
+ </tr>
+ <tr>
+ <td>Beispiel</td>
+ <td><tt>mediawiki :wiki, :layout_engine => :erb</tt></td>
+ </tr>
+</table>
+
+Da man aus dem Mediawiki-Template heraus keine Ruby-Methoden aufrufen und auch
+keine locals verwenden kann, wird man Mediawiki üblicherweise in Kombination mit
+anderen Renderern verwenden wollen:
+
+``` ruby
+erb :overview, :locals => { :text => mediawiki(:introduction) }
+```
+
+Beachte: Man kann die `mediawiki`-Methode auch aus anderen Templates
+heraus aufrufen:
+
+``` ruby
+%h1 Grüße von Haml!
+%p= mediawiki(:greetings)
+```
+
+Da man Ruby nicht von MediaWiki heraus aufrufen kann, können auch Layouts nicht
+in MediaWiki geschrieben werden. Es ist aber möglich, einen Renderer für die
+Templates zu verwenden und einen anderen für das Layout, indem die
+`:layout_engine`-Option verwendet wird.
+
#### CoffeeScript Templates
<table>
<tr>
<td>Abhängigkeit</td>
@@ -1000,12 +1074,13 @@
```
Die `:callback` und `:variable` Optionen können mit dem gerenderten Objekt
verwendet werden:
-``` ruby
-var resource = {"foo":"bar","baz":"qux"}; present(resource);
+``` javascript
+var resource = {"foo":"bar","baz":"qux"};
+present(resource);
```
#### WLang Templates
<table>
@@ -1021,33 +1096,33 @@
<td>Beispiel</td>
<td><tt>wlang :index, :locals => { :key => 'value' }</tt></td>
</tr>
</table>
-Ruby-Methoden in wlang aufzurufen entspricht nicht den idiomatischen Vorgaben
-von wlang, es bietet sich deshalb an, `:locals` zu verwenden. Layouts, die
-wlang und `yield` verwenden, werden aber trotzdem unterstützt.
+Ruby-Methoden in Wlang aufzurufen entspricht nicht den idiomatischen Vorgaben
+von Wlang, es bietet sich deshalb an, `:locals` zu verwenden. Layouts, die
+Wlang und `yield` verwenden, werden aber trotzdem unterstützt.
Rendert den eingebetteten Template-String.
### Auf Variablen in Templates zugreifen
Templates werden in demselben Kontext ausgeführt wie Routen. Instanzvariablen
in Routen sind auch direkt im Template verfügbar:
```ruby
get '/:id' do
- @foo = Foo.find(params[:id])
+ @foo = Foo.find(params['id'])
haml '%h1= @foo.name'
end
```
Oder durch einen expliziten Hash von lokalen Variablen:
```ruby
get '/:id' do
- foo = Foo.find(params[:id])
+ foo = Foo.find(params['id'])
haml '%h1= bar.name', :locals => { :bar => foo }
end
```
Dies wird typischerweise bei Verwendung von Subtemplates (partials) in anderen
@@ -1175,10 +1250,27 @@
Dieser Code rendert `./views/application.mtt`. Siehe
[github.com/rtomayko/tilt](https://github.com/rtomayko/tilt), um mehr über
Tilt zu erfahren.
+### Eigene Methoden zum Aufsuchen von Templates verwenden
+
+Um einen eigenen Mechanismus zum Aufsuchen von Templates zu
+implementieren, muss `#find_template` definiert werden:
+
+``` ruby
+configure do
+ set :views [ './views/a', './views/b' ]
+end
+
+def find_template(views, name, engine, &block)
+ Array(views).each do |v|
+ super(v, name, engine, &block)
+ end
+end
+```
+
## Filter
Before-Filter werden vor jedem Request in demselben Kontext, wie danach die
Routen, ausgeführt. So können etwa Request und Antwort geändert werden.
Gesetzte Instanzvariablen in Filtern können in Routen und Templates verwendet
@@ -1190,11 +1282,11 @@
request.path_info = '/foo/bar/baz'
end
get '/foo/*' do
@note #=> 'Hi!'
- params[:splat] #=> 'bar/baz'
+ params['splat'] #=> 'bar/baz'
end
```
After-Filter werden nach jedem Request in demselben Kontext ausgeführt und
können ebenfalls Request und Antwort ändern. In Before-Filtern gesetzte
@@ -1243,11 +1335,11 @@
"#{name}bar"
end
end
get '/:name' do
- bar(params[:name])
+ bar(params['name'])
end
```
### Sessions verwenden
Sessions werden verwendet, um Zustände zwischen den Requests zu speichern. Sind
@@ -1259,11 +1351,11 @@
get '/' do
"value = " << session[:value].inspect
end
get '/:value' do
- session[:value] = params[:value]
+ session[:value] = params['value']
end
```
Beachte, dass `enable :sessions` alle Daten in einem Cookie speichert. Unter
Umständen kann dies negative Effekte haben, z.B. verursachen viele Daten
@@ -1277,11 +1369,11 @@
get '/' do
"value = " << session[:value].inspect
end
get '/:value' do
- session[:value] = params[:value]
+ session[:value] = params['value']
end
```
Um die Sicherheit zu erhöhen, werden Cookies, die Session-Daten führen, mit
einem sogenannten Session-Secret signiert. Da sich dieses Geheimwort bei jedem
@@ -1298,10 +1390,17 @@
```ruby
set :sessions, :domain => 'foo.com'
```
+Um eine Session mit anderen Apps und zwischen verschiedenen Subdomains
+von foo.com zu teilen, wird ein *.* der Domain vorangestellt:
+
+``` ruby
+set :sessions, :domain => '.foo,com'
+```
+
### Anhalten
Zum sofortigen Stoppen eines Request in einem Filter oder einer Route:
```ruby
@@ -1342,11 +1441,11 @@
Eine Route kann mittels `pass` zu der nächsten passenden Route springen:
```ruby
get '/raten/:wer' do
- pass unless params[:wer] == 'Frank'
+ pass unless params['wer'] == 'Frank'
'Du hast mich!'
end
get '/raten/*' do
'Du hast mich nicht!'
@@ -1465,24 +1564,22 @@
set :server, :thin
connections = []
get '/subscribe' do
# Client-Registrierung beim Server, damit Events mitgeteilt werden können
- stream(:keep_open) { |out| connections << out }
-
- # tote Verbindungen entfernen
- connections.reject!(&:closed?)
-
- # Rückmeldung
- "Angemeldet"
+ stream(:keep_open) do |out|
+ connections << out
+ # tote Verbindungen entfernen
+ connections.reject!(&:closed?)
+ end
end
-post '/message' do
+post '/:message' do
connections.each do |out|
# Den Client über eine neue Nachricht in Kenntnis setzen
# notify client that a new message has arrived
- out << params[:message] << "\n"
+ out << params['message'] << "\n"
# Den Client zur erneuten Verbindung auffordern
out.close
end
@@ -1649,11 +1746,11 @@
eigentliche Arbeit anfängt, da sie sofort eine Antwort senden, wenn der Client
eine aktuelle Version im Cache vorhält:
```ruby
get '/article/:id' do
- @article = Article.find params[:id]
+ @article = Article.find params['id']
last_modified @article.updated_at
etag @article.sha1
erb :article
end
```
@@ -1709,11 +1806,12 @@
etag '', :new_resource => true, :kind => :weak
```
### Dateien versenden
-Zum Versenden von Dateien kann die `send_file`-Helfer-Methode verwendet werden:
+Um den Inhalt einer Datei als Response zurückzugeben, kann die
+`send_file`-Helfer-Methode verwendet werden:
```ruby
get '/' do
send_file 'foo.png'
end
@@ -2008,14 +2106,14 @@
einem Reverse-Proxy liegt, der nicht ordentlich eingerichtet ist. Beachte,
dass die <tt>url</tt>-Helfer-Methode nach wie vor absolute URLs erstellen
wird, es sei denn, es wird als zweiter Parameter <tt>false</tt> angegeben.
Standardmäßig nicht aktiviert.</dd>
- <dt>add_charsets</dt>
+ <dt>add_charset</dt>
<dd>Mime-Types werden hier automatisch der Helfer-Methode
<tt>content_type</tt> zugeordnet. Es empfielt sich, Werte hinzuzufügen statt
- sie zu überschreiben: <tt>settings.add_charsets << "application/foobar"</tt>
+ sie zu überschreiben: <tt>settings.add_charset << "application/foobar"</tt>
</dd>
<dt>app_file</dt>
<dd>Pfad zur Hauptdatei der Applikation. Wird verwendet, um das Wurzel-,
Inline-, View- und öffentliche Verzeichnis des Projekts festzustellen.</dd>
@@ -2123,10 +2221,13 @@
<dt>threaded</dt>
<dd>Wird es auf <tt>true</tt> gesetzt, wird Thin aufgefordert
<tt>EventMachine.defer</tt> zur Verarbeitung des Requests einzusetzen.</dd>
+ <dt>traps</dt>
+ <dd>Einstellung, Sinatra System signalen umgehen soll.</dd>
+
<dt>views</dt>
<dd>Verzeichnis der Views. Leitet sich von der <tt>app_file</tt> Einstellung
ab, wenn nicht gesetzt.</dd>
<dt>x_cascade</dt>
@@ -2170,16 +2271,23 @@
```
### Fehler
Der `error`-Handler wird immer ausgeführt, wenn eine Exception in einem
-Routen-Block oder in einem Filter geworfen wurde. Die Exception kann über die
-`sinatra.error`-Rack-Variable angesprochen werden:
+Routen-Block oder in einem Filter geworfen wurde. In der
+`development`-Umgebung wird es nur dann funktionieren, wenn die
+`:show_exceptions`-Option auf `:after_handler` eingestellt wurde:
```ruby
+set :show_exceptions, :after_handler
+```
+
+Die Exception kann über die `sinatra.error`-Rack-Variable angesprochen werden:
+
+```ruby
error do
- 'Entschuldige, es gab einen hässlichen Fehler - ' + env['sinatra.error'].name
+ 'Entschuldige, es gab einen hässlichen Fehler - ' + env['sinatra.error'].message
end
```
Benutzerdefinierte Fehler:
@@ -2227,11 +2335,11 @@
Development-Umgebung ein, um hilfreiche Debugging Informationen und Stack Traces
anzuzeigen.
## Rack-Middleware
-Sinatra baut auf [Rack](http://rack.rubyforge.org/), einem minimalistischen
+Sinatra baut auf [Rack](http://rack.github.io/), einem minimalistischen
Standard-Interface für Ruby-Webframeworks. Eines der interessantesten Features
für Entwickler ist der Support von Middlewares, die zwischen den Server und
die Anwendung geschaltet werden und so HTTP-Request und/oder Antwort
überwachen und/oder manipulieren können.
@@ -2249,11 +2357,11 @@
'Hallo Welt'
end
```
Die Semantik von `use` entspricht der gleichnamigen Methode der
-[Rack::Builder](http://rack.rubyforge.org/doc/classes/Rack/Builder.html)-DSL
+[Rack::Builder](http://rubydoc.info/github/rack/rack/master/Rack/Builder)-DSL
(meist verwendet in Rackup-Dateien). Ein Beispiel dafür ist, dass die
`use`-Methode mehrere/verschiedene Argumente und auch Blöcke entgegennimmt:
```ruby
use Rack::Auth::Basic do |username, password|
@@ -2266,25 +2374,25 @@
viele von diesen Komponenten automatisch, abhängig von der Konfiguration. So
muss `use` häufig nicht explizit verwendet werden.
Hilfreiche Middleware gibt es z.B. hier:
[rack](https://github.com/rack/rack/tree/master/lib/rack),
-[rack-contrib](https://github.com/rack/rack-contrib#readme),
+[rack-contrib](https://github.com/rack/rack-contrib#readme),
oder im [Rack wiki](https://github.com/rack/rack/wiki/List-of-Middleware).
## Testen
Sinatra-Tests können mit jedem auf Rack aufbauendem Test-Framework geschrieben
werden. [Rack::Test](http://rdoc.info/github/brynary/rack-test/master/frames)
wird empfohlen:
```ruby
require 'my_sinatra_app'
-require 'test/unit'
+require 'minitest/autorun'
require 'rack/test'
-class MyAppTest < Test::Unit::TestCase
+class MyAppTest < Minitest::Test
include Rack::Test::Methods
def app
Sinatra::Application
end
@@ -2351,16 +2459,28 @@
'sinatra/base'` aufrufen, ansonsten werden alle von Sinatras DSL-Methoden
in den Top-Level-Namespace importiert.
* Alle Routen, Error-Handler, Filter und Optionen der Applikation müssen in
einer Subklasse von `Sinatra::Base` definiert werden.
-
`Sinatra::Base` ist ein unbeschriebenes Blatt. Die meisten Optionen sind per
Standard deaktiviert. Das betrifft auch den eingebauten Server. Siehe
[Optionen und Konfiguration](http://sinatra.github.com/configuration.html) für
Details über mögliche Optionen.
+Damit eine App sich ähnlich wie eine klassische App verhält, kann man
+auch eine Subclass von `Sinatra::Application` erstellen:
+
+``` ruby
+require 'sinatra/base'
+
+class MyApp < Sinatra::Application
+ get '/' do
+ 'Hello world!'
+ end
+end
+```
+
### Modularer vs. klassischer Stil
Entgegen häufiger Meinungen gibt es nichts gegen den klassischen Stil
einzuwenden. Solange es die Applikation nicht beeinträchtigt, besteht kein
Grund, eine modulare Applikation zu erstellen.
@@ -2377,46 +2497,53 @@
<table>
<tr>
<th>Szenario</th>
<th>Classic</th>
<th>Modular</th>
+ <th>Modular</th>
</tr>
<tr>
<td>app_file</td>
<td>Sinatra ladende Datei</td>
<td>Sinatra::Base subklassierende Datei</td>
+ <td>Sinatra::Application subklassierende Datei</td>
</tr>
<tr>
<td>run</td>
<td>$0 == app_file</td>
<td>false</td>
+ <td>false</td>
</tr>
<tr>
<td>logging</td>
<td>true</td>
<td>false</td>
+ <td>true</td>
</tr>
<tr>
<td>method_override</td>
<td>true</td>
<td>false</td>
+ <td>true</td>
</tr>
<tr>
<td>inline_templates</td>
<td>true</td>
<td>false</td>
+ <td>true</td>
</tr>
<tr>
<td>static</td>
<td>true</td>
<td>false</td>
+ <td>true</td>
</tr>
</table>
### Eine modulare Applikation bereitstellen
@@ -2505,12 +2632,12 @@
enable :sessions
get('/login') { haml :login }
post('/login') do
- if params[:name] == 'admin' && params[:password] == 'admin'
- session['user_name'] = params[:name]
+ if params['name'] == 'admin' && params['password'] == 'admin'
+ session['user_name'] = params['name']
else
redirect '/login'
end
end
end
@@ -2634,12 +2761,12 @@
# Hey, ich bin im Anwendungs-Scope!
get '/neue_route/:name' do
# Anfrage-Scope für '/neue_route/:name'
@value = 42
- settings.get "/#{params[:name]}" do
- # Anfrage-Scope für "/#{params[:name]}"
+ settings.get "/#{params['name']}" do
+ # Anfrage-Scope für "/#{params['name']}"
@value # => nil (nicht dieselbe Anfrage)
end
"Route definiert!"
end
@@ -2712,10 +2839,13 @@
<dt>Ruby 1.9.3</dt>
<dd>1.9.3 wird vollständig unterstützt und empfohlen. Achtung, bei einem
Upgrade von einer früheren Version von Ruby zu Ruby 1.9.3 werden alle Sessions
ungültig. Ruby 1.9.3 wird bis Sinatra 2.0 unterstützt werden.</dd>
+<dt>Ruby 2.x</dt>
+<dd>2.x wird vollständig unterstützt.</dd>
+
<dt>Rubinius</dt>
<dd>Rubinius (Version >= 2.x) wird offiziell unterstützt. Es wird empfohlen, den
<a href="http://puma.io">Puma Server</a> zu installieren (<tt>gem install puma
</tt>)</dd>
@@ -2736,12 +2866,12 @@
Nicht offiziell unterstützt bedeutet, dass wenn Sachen nicht funktionieren,
wir davon ausgehen, dass es nicht an Sinatra sondern an der jeweiligen
Implementierung liegt.
Im Rahmen unserer CI (Kontinuierlichen Integration) wird bereits ruby-head
-(das kommende Ruby 2.1.0) mit eingebunden. Es kann davon ausgegangen
-werden, dass Sinatra Ruby 2.1.0 vollständig unterstützen wird.
+(zukünftige Versionen von MRI) mit eingebunden. Es kann davon ausgegangen
+werden, dass Sinatra MRI auch weiterhin vollständig unterstützen wird.
Sinatra sollte auf jedem Betriebssystem laufen, dass einen funktionierenden
Ruby-Interpreter aufweist.
Sinatra läuft aktuell nicht unter Cardinal, SmallRuby, BlueRuby oder Ruby <= 1.8.7.
@@ -2853,10 +2983,10 @@
* [Issue-Tracker](http://github.com/sinatra/sinatra/issues)
* [Twitter](http://twitter.com/sinatra)
* [Mailing-Liste](http://groups.google.com/group/sinatrarb)
* [#sinatra](irc://chat.freenode.net/#sinatra) auf http://freenode.net Es
gibt dort auch immer wieder deutschsprachige Entwickler, die gerne weiterhelfen.
-* [Sinatra Book](http://sinatra-book.gittr.com) Kochbuch Tutorial
+* [Sinatra Book](https://github.com/sinatra/sinatra-book/) Kochbuch Tutorial
* [Sinatra Recipes](http://recipes.sinatrarb.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