sinatra 1.2.0.c → 1.2.0.d
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sinatra might be problematic. Click here for more details.
- data/AUTHORS +10 -1
- data/Gemfile +24 -6
- data/README.de.rdoc +696 -72
- data/README.es.rdoc +545 -61
- data/README.fr.rdoc +2 -2
- data/README.jp.rdoc +2 -2
- data/README.rdoc +281 -74
- data/README.ru.rdoc +2 -2
- data/README.zh.rdoc +2 -2
- data/Rakefile +10 -7
- data/lib/sinatra/base.rb +48 -20
- data/sinatra.gemspec +4 -5
- data/test/encoding_test.rb +4 -3
- data/test/helper.rb +2 -0
- data/test/helpers_test.rb +48 -13
- data/test/rdoc_test.rb +1 -1
- data/test/routing_test.rb +5 -0
- data/test/views/{ascii.haml → ascii.erb} +1 -1
- data/test/views/{utf8.haml → utf8.erb} +1 -1
- metadata +6 -7
- data/Gemfile.lock +0 -74
data/AUTHORS
CHANGED
@@ -36,8 +36,17 @@ Sinatra would not be possible:
|
|
36
36
|
* Rick Olson (technoweenie) for the killer plug at RailsConf '08.
|
37
37
|
* Steven Garcia for the amazing custom artwork you see on 404's and 500's
|
38
38
|
* Pat Nakajima (nakajima) for fixing non-nested params in nested params Hash's.
|
39
|
-
* Konstantin Haase for his hard work and ongoing commitment to improving
|
39
|
+
* Konstantin Haase for his hard work and ongoing commitment to improving
|
40
40
|
Sinatra, for 1.1.0, 1.2.0 and beyond..
|
41
|
+
* Zachary Scott for adding Konstantin to the AUTHORS file. He also did help
|
42
|
+
writing the book, but mainly for adding Konstantin.
|
43
|
+
* Gabriel Andretta for having people wonder whether our documentation is
|
44
|
+
actually in English or in Spanish.
|
45
|
+
* Vasily Polovnyov, Nickolay Schwarz, Luciano Sousa, Wu Jiang, Mickael Riga,
|
46
|
+
Bernhard Essl, Janos Hardi, Kouhei Yanagita and "burningTyger" for willingly
|
47
|
+
translating whatever ends up in the README.
|
48
|
+
* [Wordy](http://www.wordy.com/) for proofreading our README. 73e137d
|
49
|
+
* cactus for digging through code and specs, multiple times.
|
41
50
|
|
42
51
|
and last but not least:
|
43
52
|
|
data/Gemfile
CHANGED
@@ -4,9 +4,11 @@
|
|
4
4
|
# development dependencies of our dependencies, and those are not conflict free.
|
5
5
|
# So, here we are, `bundle install`.
|
6
6
|
#
|
7
|
-
# If you have issues with
|
7
|
+
# If you have issues with a gem: `bundle install --without-coffee-script`.
|
8
8
|
|
9
|
-
|
9
|
+
RUBY_ENGINE = 'ruby' unless defined? RUBY_ENGINE
|
10
|
+
|
11
|
+
source :rubygems unless ENV['QUICK']
|
10
12
|
gemspec
|
11
13
|
|
12
14
|
gem 'rake'
|
@@ -17,12 +19,16 @@ gem 'builder', :group => 'builder'
|
|
17
19
|
gem 'erubis', :group => 'erubis'
|
18
20
|
gem 'less', :group => 'less'
|
19
21
|
gem 'liquid', :group => 'liquid'
|
20
|
-
gem 'RedCloth', :group => 'redcloth'
|
21
|
-
gem 'rdoc', :group => 'rdoc'
|
22
22
|
gem 'nokogiri', :group => 'nokogiri'
|
23
23
|
gem 'slim', :group => 'slim'
|
24
24
|
|
25
|
-
|
25
|
+
|
26
|
+
if RUBY_VERSION > '1.8.6'
|
27
|
+
gem 'coffee-script', '>= 2.0', :group => 'coffee-script'
|
28
|
+
gem 'rdoc', :group => 'rdoc'
|
29
|
+
else
|
30
|
+
gem 'rack', '~> 1.1.0'
|
31
|
+
end
|
26
32
|
|
27
33
|
platforms :ruby do
|
28
34
|
gem 'rdiscount', :group => 'rdiscount'
|
@@ -32,4 +38,16 @@ platforms :ruby_18, :jruby do
|
|
32
38
|
gem 'json', :group => 'coffee-script'
|
33
39
|
gem 'markaby', :group => 'markaby'
|
34
40
|
gem 'radius', :group => 'radius'
|
35
|
-
end
|
41
|
+
end
|
42
|
+
|
43
|
+
platforms :mri do
|
44
|
+
# bundler platforms are broken
|
45
|
+
next unless RUBY_ENGINE == 'ruby'
|
46
|
+
gem 'RedCloth', :group => 'redcloth'
|
47
|
+
end
|
48
|
+
|
49
|
+
platforms :mri_18 do
|
50
|
+
# bundler platforms are broken
|
51
|
+
next unless RUBY_ENGINE == 'ruby'
|
52
|
+
gem 'rcov', :group => 'rcov'
|
53
|
+
end
|
data/README.de.rdoc
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
= Sinatra
|
2
|
-
<i>Wichtig: Dieses Dokument ist eine Übersetzung aus dem Englischen und unter
|
2
|
+
<i>Wichtig: Dieses Dokument ist eine Übersetzung aus dem Englischen und unter
|
3
|
+
Umständen nicht auf dem aktuellsten Stand.</i>
|
3
4
|
|
4
5
|
Sinatra ist eine DSL, die das schnelle Erstellen von Webanwendungen in Ruby
|
5
6
|
mit minimalen Aufwand ermöglicht:
|
@@ -10,7 +11,7 @@ mit minimalen Aufwand ermöglicht:
|
|
10
11
|
'Hallo Welt!'
|
11
12
|
end
|
12
13
|
|
13
|
-
Einfach via rubygems installieren und starten:
|
14
|
+
Einfach via +rubygems+ installieren und starten:
|
14
15
|
|
15
16
|
gem install sinatra
|
16
17
|
ruby -rubygems myapp.rb
|
@@ -19,8 +20,8 @@ Die Seite kann nun unter http://localhost:4567 betrachtet werden.
|
|
19
20
|
|
20
21
|
== Routen
|
21
22
|
|
22
|
-
In Sinatra wird eine Route durch eine HTTP-Methode und ein URL-Muster
|
23
|
-
Ruby-Block zugeordnet.
|
23
|
+
In Sinatra wird eine Route durch eine HTTP-Methode und ein URL-Muster
|
24
|
+
definiert. Jeder dieser Routen wird ein Ruby-Block zugeordnet.
|
24
25
|
|
25
26
|
get '/' do
|
26
27
|
.. zeige etwas ..
|
@@ -37,6 +38,10 @@ Ruby-Block zugeordnet.
|
|
37
38
|
delete '/' do
|
38
39
|
.. entferne etwas ..
|
39
40
|
end
|
41
|
+
|
42
|
+
options '/' do
|
43
|
+
.. lege etwas fest ..
|
44
|
+
end
|
40
45
|
|
41
46
|
Die Routen werden in der Reihenfolge durchlaufen, in der sie definiert wurden.
|
42
47
|
Das erste Routemuster, das mit dem Request übereinstimmt, wird ausgeführt.
|
@@ -126,16 +131,19 @@ Man kann auch relativ einfach eigene Bedingungen hinzufügen:
|
|
126
131
|
Durch den Rückgabewert eines Routenblocks wird mindestens der Response Body
|
127
132
|
festgelegt, der an den HTTP Client, bzw die nächste Rack Middleware
|
128
133
|
weitergegeben wird. Im Normalfall handelt es sich hierbei, wie
|
129
|
-
in den vorangehenden Beispielen zu sehen war, um einen String. Es werden
|
130
|
-
Werte akzeptiert.
|
134
|
+
in den vorangehenden Beispielen zu sehen war, um einen String. Es werden
|
135
|
+
allerdings auch andere Werte akzeptiert.
|
131
136
|
|
132
137
|
Man kann jedes Objekt zurückgeben, bei dem es sich entweder um einenen validen
|
133
138
|
Rack-Rückgabewert, einen validen Rack-Body oder einen HTTP Status Code
|
134
139
|
handelt:
|
135
140
|
|
136
|
-
* Ein Array mit drei Elementen: <tt>[Status (Fixnum), Headers (Hash), Response
|
137
|
-
|
138
|
-
* Ein
|
141
|
+
* Ein Array mit drei Elementen: <tt>[Status (Fixnum), Headers (Hash), Response
|
142
|
+
Body (hört auf #each)]</tt>
|
143
|
+
* Ein Array mit zwei Elementen: <tt>[Status (Fixnum), Response Body (hört auf
|
144
|
+
#each)]</tt>
|
145
|
+
* Ein Objekt, das auf <tt>#each</tt> hört und den an diese Methode übergebenen
|
146
|
+
Block nur mit Strings als Übergabewerte aufruft.
|
139
147
|
* Ein Fixnum, das den Status Code festlegt.
|
140
148
|
|
141
149
|
Damit lässt sich relativ einfach Streaming implementieren:
|
@@ -175,7 +183,7 @@ Renderingmethoden rendern jeden String direkt.
|
|
175
183
|
|
176
184
|
=== Haml-Templates
|
177
185
|
|
178
|
-
Das haml gem wird benötigt, um Haml-Templates rendern zu können:
|
186
|
+
Das +haml+ gem wird benötigt, um Haml-Templates rendern zu können:
|
179
187
|
|
180
188
|
# haml muss eingebunden werden
|
181
189
|
require 'haml'
|
@@ -210,7 +218,7 @@ Dieser Code rendert <tt>./views/index.erb</tt>.
|
|
210
218
|
|
211
219
|
=== Erubis
|
212
220
|
|
213
|
-
Das erubis gem wird benötigt, um Erubis-Templates rendern zu können:
|
221
|
+
Das +erubis+ gem wird benötigt, um Erubis-Templates rendern zu können:
|
214
222
|
|
215
223
|
# erbubis muss eingebunden werden
|
216
224
|
require 'erubis'
|
@@ -221,9 +229,20 @@ Das erubis gem wird benötigt, um Erubis-Templates rendern zu können:
|
|
221
229
|
|
222
230
|
Dieser Code rendert <tt>./views/index.erubis</tt>.
|
223
231
|
|
232
|
+
Es ist auch möglich Erb mit Erubis zu ersetzen:
|
233
|
+
|
234
|
+
require 'erubis'
|
235
|
+
Tilt.register :erb, Tilt[:erubis]
|
236
|
+
|
237
|
+
get '/' do
|
238
|
+
erb :index
|
239
|
+
end
|
240
|
+
|
241
|
+
Dieser Code rendert ebenfalls <tt>./views/index.erb</tt>.
|
242
|
+
|
224
243
|
=== Builder-Templates
|
225
244
|
|
226
|
-
Das
|
245
|
+
Das +builder+ gem wird benötigt, um Builder-Templates rendern zu können:
|
227
246
|
|
228
247
|
# builder muss eingebunden werden
|
229
248
|
require 'builder'
|
@@ -236,7 +255,7 @@ Dieser Code rendert <tt>./views/index.builder</tt>.
|
|
236
255
|
|
237
256
|
=== Nokogiri-Templates
|
238
257
|
|
239
|
-
Das nokogiri gem wird benötigt, um Nokogiri-Templates rendern zu können:
|
258
|
+
Das +nokogiri+ gem wird benötigt, um Nokogiri-Templates rendern zu können:
|
240
259
|
|
241
260
|
# nokogiri muss eingebunden werden
|
242
261
|
require 'nokogiri'
|
@@ -249,7 +268,7 @@ Dieser Code rendert <tt>./views/index.nokogiri</tt>.
|
|
249
268
|
|
250
269
|
=== Sass-Templates
|
251
270
|
|
252
|
-
Das haml gem wird benötigt, um
|
271
|
+
Das +haml+ oder +sass+ gem wird benötigt, um Sass-Templates rendern zu können:
|
253
272
|
|
254
273
|
# sass muss eingebunden werden
|
255
274
|
require 'sass'
|
@@ -273,7 +292,7 @@ und individuell überschrieben werden.
|
|
273
292
|
|
274
293
|
=== Scss-Templates
|
275
294
|
|
276
|
-
Das haml gem wird benötigt, um SCSS-Templates rendern zu können:
|
295
|
+
Das +haml+ oder +sass+ gem wird benötigt, um SCSS-Templates rendern zu können:
|
277
296
|
|
278
297
|
# sass muss eingebunden werden
|
279
298
|
require 'sass'
|
@@ -297,7 +316,7 @@ und individuell überschrieben werden.
|
|
297
316
|
|
298
317
|
=== Less-Templates
|
299
318
|
|
300
|
-
Das less gem wird benötigt, um Less-Templates rendern zu können:
|
319
|
+
Das +less+ gem wird benötigt, um Less-Templates rendern zu können:
|
301
320
|
|
302
321
|
# less muss eingebunden werden
|
303
322
|
require 'less'
|
@@ -310,7 +329,7 @@ Dieser Code rendert <tt>./views/stylesheet.less</tt>.
|
|
310
329
|
|
311
330
|
=== Liquid-Templates
|
312
331
|
|
313
|
-
Das liquid gem wird benötigt, um Liquid-Templates rendern zu können:
|
332
|
+
Das +liquid+ gem wird benötigt, um Liquid-Templates rendern zu können:
|
314
333
|
|
315
334
|
# liquid muss eingebunden werden
|
316
335
|
require 'liquid'
|
@@ -328,7 +347,7 @@ aufrufen kann, will man nahezu in allen Fällen +locals+ übergeben:
|
|
328
347
|
|
329
348
|
=== Markdown-Templates
|
330
349
|
|
331
|
-
Das rdiscount gem wird benötigt, um Markdown-Templates rendern zu können:
|
350
|
+
Das +rdiscount+ gem wird benötigt, um Markdown-Templates rendern zu können:
|
332
351
|
|
333
352
|
# rdiscount muss eingebunden werden
|
334
353
|
require "rdiscount"
|
@@ -352,9 +371,45 @@ aufzurufen:
|
|
352
371
|
%h1 Hallo von Haml!
|
353
372
|
%p= markdown(:greetings)
|
354
373
|
|
374
|
+
Da man Ruby aus Markdown heraus nicht aufrufen kann, ist es nicht
|
375
|
+
möglich Layouts zu verwenden, die in Markdown geschrieben sind. Es ist aber
|
376
|
+
möglich einen anderen Renderer für das Template zu verwenden als für das
|
377
|
+
Layout, indem man die <tt>:layout_engine</tt> option angibt:
|
378
|
+
|
379
|
+
get '/' do
|
380
|
+
markdown :index, :layout_engine => :erb
|
381
|
+
end
|
382
|
+
|
383
|
+
Das wird <tt>./views/index.md</tt> mit <tt>./views/layout.erb</tt> als Layout
|
384
|
+
rendern.
|
385
|
+
|
386
|
+
Denk dran, dass man solche Einstellungen auch global setzen kann:
|
387
|
+
|
388
|
+
set :markdown, :layout_engine => :haml, :layout => :post
|
389
|
+
|
390
|
+
get '/' do
|
391
|
+
markdown :index
|
392
|
+
end
|
393
|
+
|
394
|
+
Das wird <tt>./views/index.md</tt> (und jedes andere Markdown Template) mit
|
395
|
+
<tt>./views/post.haml</tt> als Layout rendern.
|
396
|
+
|
397
|
+
Ebenso ist es möglich Markdown mit BlueCloth anstelle von RDiscount zu parsen:
|
398
|
+
|
399
|
+
require 'bluecloth'
|
400
|
+
|
401
|
+
Tilt.register 'markdown', BlueClothTemplate
|
402
|
+
Tilt.register 'mkd', BlueClothTemplate
|
403
|
+
Tilt.register 'md', BlueClothTemplate
|
404
|
+
|
405
|
+
get '/' do
|
406
|
+
markdown :index
|
407
|
+
end
|
408
|
+
|
409
|
+
Das sollte <tt>./views/index.md</tt> mit BlueCloth rendern.
|
355
410
|
=== Textile-Templates
|
356
411
|
|
357
|
-
Das
|
412
|
+
Das +redcloth+ gem wird benötigt, um Textile-Templates rendern zu können:
|
358
413
|
|
359
414
|
# redcloth muss eingebunden werden
|
360
415
|
require "redcloth"
|
@@ -377,12 +432,36 @@ aufzurufen:
|
|
377
432
|
%h1 Hallo von Haml!
|
378
433
|
%p= textile(:greetings)
|
379
434
|
|
435
|
+
Da man Ruby aus Textile heraus nicht aufrufen kann, ist es nicht
|
436
|
+
möglich Layouts zu verwenden, die in Textile geschrieben sind. Es ist aber
|
437
|
+
möglich einen anderen Renderer für das Template zu verwenden als für das
|
438
|
+
Layout, indem man die <tt>:layout_engine</tt> option angibt:
|
439
|
+
|
440
|
+
get '/' do
|
441
|
+
textile :index, :layout_engine => :erb
|
442
|
+
end
|
443
|
+
|
444
|
+
Das wird <tt>./views/index.textile</tt> mit
|
445
|
+
<tt>./views/layout.erb</tt> als Layout
|
446
|
+
rendern.
|
447
|
+
|
448
|
+
Denk dran, dass man solche Einstellungen auch global setzen kann:
|
449
|
+
|
450
|
+
set :textile, :layout_engine => :haml, :layout => :post
|
451
|
+
|
452
|
+
get '/' do
|
453
|
+
textile :index
|
454
|
+
end
|
455
|
+
|
456
|
+
Das wird <tt>./views/index.textile</tt> (und jedes andere Markdown Template)
|
457
|
+
mit <tt>./views/post.haml</tt> als Layout rendern.
|
458
|
+
|
380
459
|
=== RDoc-Templates
|
381
460
|
|
382
|
-
Das rdoc gem wird benötigt, um RDoc-Templates rendern zu können:
|
461
|
+
Das +rdoc+ gem wird benötigt, um RDoc-Templates rendern zu können:
|
383
462
|
|
384
463
|
# RDoc muss eingebunden werden
|
385
|
-
require "rdoc"
|
464
|
+
require "rdoc/markup/to_html"
|
386
465
|
|
387
466
|
get '/' do
|
388
467
|
rdoc :index
|
@@ -402,9 +481,34 @@ aufzurufen:
|
|
402
481
|
%h1 Hallo von Haml!
|
403
482
|
%p= rdoc(:greetings)
|
404
483
|
|
484
|
+
Da man Ruby aus RDoc heraus nicht aufrufen kann, ist es nicht
|
485
|
+
möglich Layouts zu verwenden, die in RDoc geschrieben sind. Es ist aber
|
486
|
+
möglich einen anderen Renderer für das Template zu verwenden als für das
|
487
|
+
Layout, indem man die <tt>:layout_engine</tt> option angibt:
|
488
|
+
|
489
|
+
get '/' do
|
490
|
+
rdoc :index, :layout_engine => :erb
|
491
|
+
end
|
492
|
+
|
493
|
+
Das wird <tt>./views/index.rdoc</tt> mit
|
494
|
+
<tt>./views/layout.erb</tt> als Layout
|
495
|
+
rendern.
|
496
|
+
|
497
|
+
Denk dran, dass man solche Einstellungen auch global setzen kann:
|
498
|
+
|
499
|
+
set :rdoc, :layout_engine => :haml, :layout => :post
|
500
|
+
|
501
|
+
get '/' do
|
502
|
+
rdoc :index
|
503
|
+
end
|
504
|
+
|
505
|
+
Das wird <tt>./views/index.rdoc</tt> (und jedes andere Markdown Template) mit
|
506
|
+
<tt>./views/post.haml</tt> als Layout rendern.
|
507
|
+
|
508
|
+
|
405
509
|
=== Radius-Templates
|
406
510
|
|
407
|
-
Das radius gem wird benötigt, um Radius-Templates rendern zu können:
|
511
|
+
Das +radius+ gem wird benötigt, um Radius-Templates rendern zu können:
|
408
512
|
|
409
513
|
# radius muss eingebunden werden
|
410
514
|
require 'radius'
|
@@ -422,7 +526,7 @@ aufrufen kann, will man nahezu in allen Fällen +locals+ übergeben:
|
|
422
526
|
|
423
527
|
=== Markaby-Templates
|
424
528
|
|
425
|
-
Das markaby gem wird benötigt, um Markaby-Templates rendern zu können:
|
529
|
+
Das +markaby+ gem wird benötigt, um Markaby-Templates rendern zu können:
|
426
530
|
|
427
531
|
# markaby muss eingebunden werden
|
428
532
|
require 'markaby'
|
@@ -435,7 +539,7 @@ Dieser Code rendert <tt>./views/index.mab</tt>.
|
|
435
539
|
|
436
540
|
=== Slim-Templates
|
437
541
|
|
438
|
-
Das slim gem wird benötigt, um Slim-Templates rendern zu können:
|
542
|
+
Das +slim+ gem wird benötigt, um Slim-Templates rendern zu können:
|
439
543
|
|
440
544
|
# slim muss eingebunden werden
|
441
545
|
require 'slim'
|
@@ -448,7 +552,17 @@ Dieser Code rendert <tt>./views/index.slim</tt>.
|
|
448
552
|
|
449
553
|
=== CoffeeScript-Templates
|
450
554
|
|
451
|
-
Das coffee
|
555
|
+
Das +coffee+-script gem und mindestens eine der folgenden Optionen werden
|
556
|
+
benötigt, um JavaScript auf dem Server ausführen zu können:
|
557
|
+
|
558
|
+
* +node+ (von Node.js) befindet sich im Pfad
|
559
|
+
* du bist unter OS X
|
560
|
+
* +therubyracer+ gem/library
|
561
|
+
|
562
|
+
Siehe auch http://github.com/josh/ruby-coffee-script für eine vollständige
|
563
|
+
Liste aller Optionen.
|
564
|
+
|
565
|
+
Nun kannst Du CoffeeScript Templates in Deiner App rendern:
|
452
566
|
|
453
567
|
# coffee-script muss eingebunden werden
|
454
568
|
require 'coffee-script'
|
@@ -535,21 +649,32 @@ verwendet. Durch <tt>:layout => false</tt> kann das Ausführen verhindert werden
|
|
535
649
|
haml :index, :layout => !request.xhr?
|
536
650
|
end
|
537
651
|
|
538
|
-
|
652
|
+
=== Datieendungen zuordnen
|
539
653
|
|
540
|
-
|
541
|
-
|
654
|
+
Um eine Dateiendung einer Template Engine zuzuordnen, benutzt man am besten
|
655
|
+
<tt>Tilt.register</tt>. Wenn man zum Beispiel die Dateiendung +tt+ für Textile
|
656
|
+
Templates nutzen möchte, so lässt sich das wie folgt bewerkstelligen:
|
657
|
+
|
658
|
+
Tilt.register :tt, Tilt[:textile]
|
659
|
+
|
660
|
+
=== Eine eigene Template Engine hinzufügen
|
661
|
+
|
662
|
+
Zu allererst muss man die Engine bei Tilt registrieren und danach eine
|
663
|
+
Rendering-Methode erstellen:
|
664
|
+
|
665
|
+
Tilt.register :mtt, MeineTolleTemplateEngine
|
542
666
|
|
543
667
|
helpers do
|
544
|
-
def
|
545
|
-
"#{name}bar"
|
546
|
-
end
|
668
|
+
def mtt(*args) render(:mtt, *args) end
|
547
669
|
end
|
548
670
|
|
549
|
-
get '
|
550
|
-
|
671
|
+
get '/' do
|
672
|
+
mtt :index
|
551
673
|
end
|
552
674
|
|
675
|
+
Dieser Code rendert <tt>./views/application.mtt</tt>. Siehe
|
676
|
+
https://github.com/rtomayko/tilt um mehr über Tilt zu lernen.
|
677
|
+
|
553
678
|
== Filter
|
554
679
|
|
555
680
|
Before-Filter werden immer vor jedem Request in dem selben Kontext wie danach
|
@@ -574,7 +699,8 @@ Instanzvariablen können in After-Filterm verwendet werden:
|
|
574
699
|
puts response.status
|
575
700
|
end
|
576
701
|
|
577
|
-
Filter können optional auch mit einem Pattern ausgestattet werden, welche auf
|
702
|
+
Filter können optional auch mit einem Pattern ausgestattet werden, welche auf
|
703
|
+
den Request-Pfad passen müssen, damit der Filter ausgeführt wird:
|
578
704
|
|
579
705
|
before '/protected/*' do
|
580
706
|
authenticate!
|
@@ -584,7 +710,8 @@ Filter können optional auch mit einem Pattern ausgestattet werden, welche auf d
|
|
584
710
|
session[:last_slug] = slug
|
585
711
|
end
|
586
712
|
|
587
|
-
Ähnlich wie Routen können Filter auch mit weiteren Bedingungen eingeschränkt
|
713
|
+
Ähnlich wie Routen können Filter auch mit weiteren Bedingungen eingeschränkt
|
714
|
+
werden:
|
588
715
|
|
589
716
|
before :agent => /Songbird/ do
|
590
717
|
# ...
|
@@ -594,6 +721,21 @@ Filter können optional auch mit einem Pattern ausgestattet werden, welche auf d
|
|
594
721
|
# ...
|
595
722
|
end
|
596
723
|
|
724
|
+
== Helfer
|
725
|
+
|
726
|
+
Durch die Top-Level <tt>helpers</tt>-Methode, werden sogenannte Helfer-Methoden
|
727
|
+
definiert, die in Routen und Templates verwendet werden können:
|
728
|
+
|
729
|
+
helpers do
|
730
|
+
def bar(name)
|
731
|
+
"#{name}bar"
|
732
|
+
end
|
733
|
+
end
|
734
|
+
|
735
|
+
get '/:name' do
|
736
|
+
bar(params[:name])
|
737
|
+
end
|
738
|
+
|
597
739
|
== Anhalten
|
598
740
|
|
599
741
|
Zum sofortigen stoppen eines Request in einem Filter oder einer Route:
|
@@ -633,9 +775,173 @@ Der Block wird sofort verlassen und es wird nach der nächsten treffenden Route
|
|
633
775
|
gesucht. Ein 404 Fehler wird zurückgegeben, wenn kein treffendes Routen-Muster
|
634
776
|
gefunden wird.
|
635
777
|
|
778
|
+
=== Eine andere Route ansteuern
|
779
|
+
|
780
|
+
Manchmal entspricht +pass+ nicht den Anforderungen, wenn das Ergebnis einer
|
781
|
+
anderen Route gefordert wird. Um das zu erreichen, lässt sich +call+ nutzen:
|
782
|
+
|
783
|
+
get '/foo' do
|
784
|
+
status, headers, body = call request.env.merge("PATH_INFO" => '/bar')
|
785
|
+
[status, body.upcase]
|
786
|
+
end
|
787
|
+
|
788
|
+
get '/bar' do
|
789
|
+
"bar"
|
790
|
+
end
|
791
|
+
|
792
|
+
Beachte, dass in dem oben angegeben Beispiel die Performance erheblich erhöht
|
793
|
+
werden kann, wenn man +"bar"+ in eine Helfermethode umwandelt, auf die +/foo+
|
794
|
+
und +/bar+ zugreifen können.
|
795
|
+
|
796
|
+
Wenn der Request innerhalb der gleichen App-Instanz aufgerufen und keine
|
797
|
+
Kopie der Instanz erzeugt werden soll, dann verwende +call!+ anstelle von
|
798
|
+
+call+.
|
799
|
+
|
800
|
+
Die Rack Spezifikationen enthalten weitere Informationen zu +call+.
|
801
|
+
|
802
|
+
=== Body, Status Code und Header setzen
|
803
|
+
|
804
|
+
Es ist möglich und empfohlen den Status Code sowie den Response Body mit einem
|
805
|
+
Returnwert in der Route zu setzen. In manchen Situationen kann es jedoch sein,
|
806
|
+
dass der Body an irgendeiner anderen Stelle während der Ausführung gesetzt
|
807
|
+
wird. Das lässt sich mit der Helfermethode +body+ bewerkstelligen. Wird +body+
|
808
|
+
verwendet, dann lässt sich der Body jederzeit über diese Methode aufrufen:
|
809
|
+
|
810
|
+
get '/foo' do
|
811
|
+
body "bar"
|
812
|
+
end
|
813
|
+
|
814
|
+
after do
|
815
|
+
puts body
|
816
|
+
end
|
817
|
+
|
818
|
+
Ebenso ist es möglich einen Block an +body+ weiterzureichen, der dann vom Rack
|
819
|
+
Handler ausgeführt wird (lässt sich z.B. zur Umsetzung von Streaming einsetzen,
|
820
|
+
siehe auch "Rückgabewerte").
|
821
|
+
|
822
|
+
Vergleichbar mit +body+ lassen sich auch Status Code und Header setzen:
|
823
|
+
|
824
|
+
get '/foo' do
|
825
|
+
status 418
|
826
|
+
headers \
|
827
|
+
"Allow" => "BREW, POST, GET, PROPFIND, WHEN"
|
828
|
+
"Refresh" => "Refresh: 20; http://www.ietf.org/rfc/rfc2324.txt"
|
829
|
+
halt "Ich bin ein Teekesselchen"
|
830
|
+
end
|
831
|
+
|
832
|
+
Genau wie bei +body+, liest ein Aufrufen von +headers+ oder +status+ ohne
|
833
|
+
Argumente den aktuellen Wert aus.
|
834
|
+
|
835
|
+
== Mime-Types
|
836
|
+
|
837
|
+
Wenn <tt>send_file</tt> oder statische Dateien verwendet werden, kann es
|
838
|
+
vorkommen, dass Sinatra den Mime-Typ nicht kennt. Registriert wird dieser mit
|
839
|
+
+mime_type+ per Dateiendung:
|
840
|
+
|
841
|
+
mime_type :foo, 'text/foo'
|
842
|
+
|
843
|
+
Es kann aber auch der +content_type+ Helfer verwendet werden:
|
844
|
+
|
845
|
+
get '/' do
|
846
|
+
content_type :foo
|
847
|
+
"foo foo foo"
|
848
|
+
end
|
849
|
+
|
850
|
+
=== URLs generieren
|
851
|
+
|
852
|
+
Zum Generieren von URLs sollte man die +url+ Helfermethode nutzen, so z.B.
|
853
|
+
beim Einsatz von Haml:
|
854
|
+
|
855
|
+
%a{:href => url('/foo')} foo
|
856
|
+
|
857
|
+
Soweit vorhanden, wird Rücksicht auf Proxies und Rack Router genommen.
|
858
|
+
|
859
|
+
Diese Methode ist ebenso über den Alias +to+ zu erreichen (siehe Beispiel
|
860
|
+
unten).
|
861
|
+
|
862
|
+
=== Browserumleitung
|
863
|
+
|
864
|
+
Eine Browserumleitung kann mit Hilfe der +redirect+ Hilfsmethode erreicht
|
865
|
+
werden:
|
866
|
+
|
867
|
+
get '/foo' do
|
868
|
+
redirect to('/bar')
|
869
|
+
end
|
870
|
+
|
871
|
+
Weitere Parameter werden wie Argumente der +halt+ Methode behandelt:+:
|
872
|
+
|
873
|
+
redirect to('/bar'), 303
|
874
|
+
redirect 'http://google.com', 'Hier bist Du falsch'
|
875
|
+
|
876
|
+
Ebenso leicht lässt sich ein Schritt zurück mit dem Alias
|
877
|
+
<tt>redirect back</tt> erreichen:
|
878
|
+
|
879
|
+
get '/foo' do
|
880
|
+
"<a href='/bar'>mach was</a>"
|
881
|
+
end
|
882
|
+
|
883
|
+
get '/bar' do
|
884
|
+
mach_was
|
885
|
+
redirect back
|
886
|
+
end
|
887
|
+
|
888
|
+
Um Argumente an ein Redirect weiterzugeben, fügt man sie entweder dem Query
|
889
|
+
hinzu:
|
890
|
+
|
891
|
+
redirect to('/bar?summe=42')
|
892
|
+
|
893
|
+
Oder man verwendet eine Session:
|
894
|
+
|
895
|
+
enable :session
|
896
|
+
|
897
|
+
get '/foo' do
|
898
|
+
session[:secret] = 'foo'
|
899
|
+
redirect to('/bar')
|
900
|
+
end
|
901
|
+
|
902
|
+
get '/bar' do
|
903
|
+
session[:secret]
|
904
|
+
end
|
905
|
+
|
906
|
+
=== Dateien versenden
|
907
|
+
|
908
|
+
Zum versenden von Dateien kann die <tt>send_file</tt> Helfermethode verwende
|
909
|
+
werden:
|
910
|
+
|
911
|
+
get '/' do
|
912
|
+
send_file 'foo.png'
|
913
|
+
end
|
914
|
+
|
915
|
+
Für <tt>send_file</tt> stehen einige Hash-Optionen zur Verfügung:
|
916
|
+
|
917
|
+
send_file 'foo.png', :type => :jpg
|
918
|
+
|
919
|
+
[filename]
|
920
|
+
Dateiname als Response. Standartwert ist der eigentliche Dateiname
|
921
|
+
|
922
|
+
[last_modified]
|
923
|
+
Wert für den Last-Modified Header, Standardwert ist +mtime+ der Datei.
|
924
|
+
|
925
|
+
[type]
|
926
|
+
content type der verwendet werden soll. Wird, wenn nicht angegeben, von der
|
927
|
+
Dateiendung abgeleitet.
|
928
|
+
|
929
|
+
[disposition]
|
930
|
+
Verwendet für Content-Disposition. Mögliche Werte sind: +nil+ (Standard),
|
931
|
+
<tt>:attachment</tt> und <tt>:inline</tt>
|
932
|
+
|
933
|
+
[length]
|
934
|
+
Content-Length Header. Standardwert ist die Dateigröße
|
935
|
+
|
936
|
+
Soweit vom Rack Handler unterstützt, werden neben der Übertragung über den Ruby
|
937
|
+
Prozess auch andere Möglichkeiten genutzt. Bei Verwendung der
|
938
|
+
<tt>send_file</tt> Helfermethode kümmert sich Sinatra selbständig um die
|
939
|
+
Range Requests.
|
940
|
+
|
636
941
|
== Das Request-Objekt
|
637
942
|
|
638
|
-
Auf das
|
943
|
+
Auf das +request+-Objeket der eigehenden Anfrage kann man vom Anfragescope aus
|
944
|
+
zugreifen:
|
639
945
|
|
640
946
|
# App läuft unter http://example.com/example
|
641
947
|
get '/foo' do
|
@@ -652,14 +958,15 @@ Auf das `request`-Objeket der eigehenden Anfrage kann man vom Anfragescope aus z
|
|
652
958
|
request.get? # true (ähnliche Methoden für andere Verben)
|
653
959
|
request.form_data? # false
|
654
960
|
request["SOME_HEADER"] # Wert des SOME_HEADER-headers
|
655
|
-
request.
|
961
|
+
request.referrer # der Referrer des Clients oder '/'
|
656
962
|
request.user_agent # User Agent (genutzt von :agent-Bedingung)
|
657
963
|
request.cookies # Hash der Cookies
|
658
964
|
request.xhr? # Ist dies eine Ajax-Anfrage?
|
659
965
|
request.url # "http://example.com/example/foo"
|
660
966
|
request.path # "/example/foo"
|
661
967
|
request.ip # Client IP-Addresse
|
662
|
-
request.secure? # false
|
968
|
+
request.secure? # false (wäre true bei SSL)
|
969
|
+
request.forwarded? # true (wenn hinter Reverse Proxy)
|
663
970
|
requuest.env # env-Hash den Rack durchreicht
|
664
971
|
end
|
665
972
|
|
@@ -680,12 +987,71 @@ Der <tt>request.body</tt> ist einn IO- oder StringIO-Objekt:
|
|
680
987
|
"Hallo #{daten['name']}!"
|
681
988
|
end
|
682
989
|
|
990
|
+
|
991
|
+
=== Nachschlagen von Template Dateien
|
992
|
+
|
993
|
+
Die <tt>find_template</tt> Helfermethode wird genutzt, um Template Dateien zum
|
994
|
+
Rendern aufzufinden:
|
995
|
+
|
996
|
+
find_template settings.views, 'foo', Tilt[:haml] do |file|
|
997
|
+
puts "könnte diese hier sein: #{file}"
|
998
|
+
end
|
999
|
+
|
1000
|
+
Das ist zwar nicht wirklich brauchbar, aber wenn man sie überschreibt, kann sie
|
1001
|
+
nützlich werden, um eigene Nachschlagemechanismen einzubauen. Zum Beispiel
|
1002
|
+
dann, wenn man mehr als nur ein view-Verzeichnis verwenden möchte:
|
1003
|
+
|
1004
|
+
set :views, ['views', 'templates']
|
1005
|
+
|
1006
|
+
helpers do
|
1007
|
+
def find_template(views, name, engine, &block)
|
1008
|
+
Array(views).each { |v| super(v, name, engine, &block) }
|
1009
|
+
end
|
1010
|
+
end
|
1011
|
+
|
1012
|
+
Ein anderes Beispiel wäre es verschiedene Vereichnisse für verschiedene Engines
|
1013
|
+
zu verwenden:
|
1014
|
+
|
1015
|
+
set :views, :sass => 'views/sass', :haml => 'templates', :default => 'views'
|
1016
|
+
|
1017
|
+
helpers do
|
1018
|
+
def find_template(views, name, engine, &block)
|
1019
|
+
_, folder = views.detect { |k,v| engine == Tilt[k] }
|
1020
|
+
folder ||= views[:default]
|
1021
|
+
super(folder, name, engine, &block)
|
1022
|
+
end
|
1023
|
+
end
|
1024
|
+
|
1025
|
+
Ebensogut könnte man eine Extension schreiben und diese dann mit anderen
|
1026
|
+
teilen!
|
1027
|
+
|
1028
|
+
Beachte, dass <tt>find_template</tt> nicht prüft, ob eine Datei tatsächlich
|
1029
|
+
existiert. Es wird lediglich der angegebene Block aufgerufen und nach allen
|
1030
|
+
möglichen Pfaden gesucht. Das ergibt kein Performanceproblem, da +render+
|
1031
|
+
+block+ verwendet, sobald eine Datei gefunden wurde. Ebenso werden
|
1032
|
+
Templatepfade samt Inhalt gecached, solange man nicht im Entwicklungsmodus ist.
|
1033
|
+
Das sollte man im Hinterkopf behalten, wenn man irgendwelche verrückten
|
1034
|
+
Methoden zusammenbastelt.
|
1035
|
+
|
683
1036
|
== Konfiguration
|
684
1037
|
|
685
1038
|
Wird einmal beim Starten in jedweder Umgebung ausgeführt:
|
686
1039
|
|
687
1040
|
configure do
|
688
|
-
|
1041
|
+
# setze eine Option
|
1042
|
+
set :option, 'wert'
|
1043
|
+
|
1044
|
+
# setze mehrere Optionen
|
1045
|
+
set :a => 1, :b => 2
|
1046
|
+
|
1047
|
+
# das gleiche wie `set :option, true`
|
1048
|
+
enable :option
|
1049
|
+
|
1050
|
+
# das gleiche wie `set :option, false`
|
1051
|
+
disable :option
|
1052
|
+
|
1053
|
+
# Dynamische Einstellungen mit Blöcken
|
1054
|
+
set(:css_dir) { File.join(views, 'css') }
|
689
1055
|
end
|
690
1056
|
|
691
1057
|
Läuft nur, wenn die Umgebung (RACK_ENV Umgebungsvariable) auf
|
@@ -702,6 +1068,116 @@ gesetzt ist:
|
|
702
1068
|
...
|
703
1069
|
end
|
704
1070
|
|
1071
|
+
Zugang zu diesen Einstellungen bekommt man über +settings+:
|
1072
|
+
|
1073
|
+
configure do
|
1074
|
+
set :foo, 'bar'
|
1075
|
+
end
|
1076
|
+
|
1077
|
+
get '/' do
|
1078
|
+
settings.foo? # => true
|
1079
|
+
settings.foo # => 'bar'
|
1080
|
+
...
|
1081
|
+
end
|
1082
|
+
|
1083
|
+
=== Mögliche Einstellungen
|
1084
|
+
|
1085
|
+
[absolute_redirects] Wenn ausgeschaltet wird Sinatra relative Redirects
|
1086
|
+
zulassen. Jedoch ist Sinatra dann nicht mehr mit RFC 2616
|
1087
|
+
(HTTP 1.1) konform, das nur absolute Redirects zulässt.
|
1088
|
+
|
1089
|
+
Sollte eingeschaltet werden, wenn man hinter einem
|
1090
|
+
Reverse Proxy ist, der nicht ordentlich eingerichtet ist.
|
1091
|
+
Beachte, dass die +url+ Helfermethode nach wie vor
|
1092
|
+
absolute URLs erstellen wird, es sei denn man gibt als
|
1093
|
+
zweiten Parameter +false+ an.
|
1094
|
+
|
1095
|
+
Standardmäßig nicht aktiviert.
|
1096
|
+
|
1097
|
+
|
1098
|
+
[add_charsets] Mime Types werden hier automatisch der Helfermethode
|
1099
|
+
<tt>content_type</tt> zugeordnet.
|
1100
|
+
|
1101
|
+
Es empfielt sich Werte hinzuzufügen anstellen von
|
1102
|
+
überschreiben:
|
1103
|
+
|
1104
|
+
settings.add_charsets << "application/foobar"
|
1105
|
+
|
1106
|
+
[app_file] Hauptdatei der Applikation. Wird verwendet, um das
|
1107
|
+
Wurzel-, Inline-, View- und öffentliche Verzeichnis des
|
1108
|
+
Projekts festzustellen.
|
1109
|
+
|
1110
|
+
[bind] IP Address an die gebunden wird (Standardwert: 0.0.0.0).
|
1111
|
+
Wird nur für den eingebauten Server verwendet.
|
1112
|
+
|
1113
|
+
[default_encoding] Das Encoding, falls keines angegeben wurde.
|
1114
|
+
Standardwert ist <tt>"utf-8"</tt>.
|
1115
|
+
|
1116
|
+
[dump_errors] Fehler im Log anzeigen.
|
1117
|
+
|
1118
|
+
[environment] Momentane Umgebung. Standardmäßig auf
|
1119
|
+
<tt>content_type</tt> eingestellt oder
|
1120
|
+
<tt>"development"</tt> soweit ersteres nicht vorhanden.
|
1121
|
+
|
1122
|
+
[logging] Den Logger verwenden.
|
1123
|
+
|
1124
|
+
[lock] Jeder Request wird gelocked. Es kann nur ein Request pro
|
1125
|
+
Ruby Prozess gleichzeitig verarbeitet werden.
|
1126
|
+
|
1127
|
+
Eingeschaltet wenn die Application Thread-Safe ist.
|
1128
|
+
Standardmäßig nicht aktiviert.
|
1129
|
+
|
1130
|
+
[method_override] Verwende <tt>_method</tt>, um put/delete Formulardaten in
|
1131
|
+
Browsern zu verwenden, die dies normalerweise nicht
|
1132
|
+
unterstützen.
|
1133
|
+
|
1134
|
+
[port] Port für die Applikation. Wird nur im internen Server
|
1135
|
+
verwendet.
|
1136
|
+
|
1137
|
+
[prefixed_redirects] Entscheidet, ob <tt>request.script_name</tt> in Redirects
|
1138
|
+
eingefügt wird oder nicht, wenn kein absoluter Pfad
|
1139
|
+
angegeben ist. Auf diese Art und Weise verhält sich
|
1140
|
+
<tt>redirect '/foo'</tt> so als ob es ein
|
1141
|
+
<tt>redirect to('/foo')</tt> wäre.
|
1142
|
+
Standardmäßig nicht aktiviert.
|
1143
|
+
|
1144
|
+
[public] Das öffentliche Verzeichnis aus dem Daten zur Verfügung
|
1145
|
+
gestellt werden können.
|
1146
|
+
|
1147
|
+
[reload_templates] Entscheidet, ob Templates zwischen Anfragen neu geladen
|
1148
|
+
werden sollen oder nicht. Unter Ruby 1.8.6 ist es im
|
1149
|
+
Entwicklungsmodus eingeschaltet (um einen Fehler in Ruby
|
1150
|
+
auszugleichen, der ein Speicherleck verursacht).
|
1151
|
+
|
1152
|
+
[root] Wurzelverzeichnis des Projekts.
|
1153
|
+
|
1154
|
+
[raise_errors] Einen Ausnahmezustand aufrufen. Beendet die Applikation.
|
1155
|
+
|
1156
|
+
[run] Wenn aktiviert, wird Sinatra versuchen den Webserver zu
|
1157
|
+
starten. Nicht verwenden, wenn Rackup oder anderes
|
1158
|
+
verwendet werden soll.
|
1159
|
+
|
1160
|
+
[running] Läuft der eingebaute Server? Diese Einstellung nicht
|
1161
|
+
ändern!
|
1162
|
+
|
1163
|
+
[server] Server oder Liste von Servern die als eingebaute Server
|
1164
|
+
zur Verfügung stehen.
|
1165
|
+
Standardmäßig auf ['thin', 'mongrel', 'webrick']
|
1166
|
+
voreingestellt. Die Anordnung gibt die Priorität vor.
|
1167
|
+
|
1168
|
+
[sessions] Sessions auf Cookiebasis aktivieren.
|
1169
|
+
|
1170
|
+
[show_exceptions] Stacktrace im Browser bei Fehlern anzeigen.
|
1171
|
+
|
1172
|
+
[static] Entscheidet, ob Sinatra statische Dateien zur Verfügung
|
1173
|
+
stellen soll oder nicht.
|
1174
|
+
Sollte nicht aktiviert werden, wenn ein Server verwendet
|
1175
|
+
wird, der dies auch selbständig erledigen kann.
|
1176
|
+
Deaktivieren wird die Performance erhöhen.
|
1177
|
+
Standardmäßig aktiviert.
|
1178
|
+
|
1179
|
+
[views] Verzeichnis der Views.
|
1180
|
+
|
705
1181
|
== Fehlerbehandlung
|
706
1182
|
|
707
1183
|
Error Handler laufen im selben Kontext wie Routen und Filter, was bedeutet,
|
@@ -710,7 +1186,8 @@ verwendet werden können.
|
|
710
1186
|
|
711
1187
|
=== Nicht gefunden
|
712
1188
|
|
713
|
-
Wenn eine <tt>Sinatra::NotFound</tt> Exception geworfen wird oder der
|
1189
|
+
Wenn eine <tt>Sinatra::NotFound</tt> Exception geworfen wird oder der
|
1190
|
+
Statuscode 404 ist, wird der <tt>not_found</tt> Handler ausgeführt:
|
714
1191
|
|
715
1192
|
not_found do
|
716
1193
|
'Seite kann nirgendwo gefunden werden.'
|
@@ -718,8 +1195,8 @@ Wenn eine <tt>Sinatra::NotFound</tt> Exception geworfen wird oder der Statuscode
|
|
718
1195
|
|
719
1196
|
=== Fehler
|
720
1197
|
|
721
|
-
Der +error+ Handler wird immer ausgeführt, wenn eine Exception in einem
|
722
|
-
oder in einen Filter geworfen wurde. Die Exception kann über die
|
1198
|
+
Der +error+ Handler wird immer ausgeführt, wenn eine Exception in einem
|
1199
|
+
Routenblock oder in einen Filter geworfen wurde. Die Exception kann über die
|
723
1200
|
<tt>sinatra.error</tt> Rack-Variable angesprochen werden:
|
724
1201
|
|
725
1202
|
error do
|
@@ -761,21 +1238,10 @@ Oder ein Statuscode-Bereich:
|
|
761
1238
|
Sinatra setzt verschiedene <tt>not_found</tt> und <tt>error</tt>
|
762
1239
|
Handler in der Development Umgebung.
|
763
1240
|
|
764
|
-
== Mime-Types
|
765
|
-
|
766
|
-
Wenn <tt>send_file</tt> oder statische Dateien verwendet werden, kann es
|
767
|
-
vorkommen, dass Sinatra den Mime-Typ nicht kennt. Registriert wird dieser mit
|
768
|
-
+mime_type+ per Dateiendung:
|
769
|
-
|
770
|
-
mime_type :foo, 'text/foo'
|
771
|
-
|
772
|
-
Es kann aber auch der +content_type+ Helfer verwendet werden:
|
773
|
-
|
774
|
-
content_type :foo
|
775
|
-
|
776
1241
|
== Rack Middleware
|
777
1242
|
|
778
|
-
Sinatra baut auf Rack[http://rack.rubyforge.org/], einem minimalen
|
1243
|
+
Sinatra baut auf Rack[http://rack.rubyforge.org/], einem minimalen
|
1244
|
+
Standardinterface für Ruby Webframeworks. Eines der interessantesten
|
779
1245
|
Features für Entwickler ist der Support von Middleware, die
|
780
1246
|
zwischen den Server und die Anwendung geschaltet wird und so HTTP
|
781
1247
|
Request und/oder Antwort überwachen und/oder manipulieren kann.
|
@@ -848,7 +1314,8 @@ Das Definitieren einer Top-Level Anwendung funktioniert gut für
|
|
848
1314
|
Microanwendungen, hat aber Nachteile, wenn man wiederverwendbare Komponenten
|
849
1315
|
wie Middleware, Rails Metal, einfache Bibliotheken mit Server Komponenten
|
850
1316
|
oder auch Sinatra Erweiterungen bauen will.
|
851
|
-
Die Top-Level DSL belastet den Objekt-Namespace und setzt einen
|
1317
|
+
Die Top-Level DSL belastet den Objekt-Namespace und setzt einen
|
1318
|
+
Microanwendungsstil voraus (eine einzelne Anwendungsdatei, ./public und ./views
|
852
1319
|
Ordner, Logging, Exception-Detail-Seite, usw.). Genau hier kommt Sinatra::Base
|
853
1320
|
ins Spiel:
|
854
1321
|
|
@@ -871,7 +1338,8 @@ einer Bibliothek:
|
|
871
1338
|
MyApp.run! :host => 'localhost', :port => 9090
|
872
1339
|
|
873
1340
|
Die Methoden der Sinatra::Base-Subklasse sind genau die selben wie die
|
874
|
-
der Top-Level DSL. Die meisten Top-Level Anwendungen können mit nur zwei
|
1341
|
+
der Top-Level DSL. Die meisten Top-Level Anwendungen können mit nur zwei
|
1342
|
+
Veränderungen zu Sinatra::Base-Komponenten konvertiert werden:
|
875
1343
|
|
876
1344
|
* Die Datei sollte <tt>require 'sinatra/base'</tt> anstelle von
|
877
1345
|
<tt>require 'sinatra/base'</tt> aufrufen, ansonsten werden alle von
|
@@ -879,7 +1347,100 @@ der Top-Level DSL. Die meisten Top-Level Anwendungen können mit nur zwei Verän
|
|
879
1347
|
* Alle Routen, Error Handler, Filter und Optionen der Applikation müssen in
|
880
1348
|
einer Subklasse von Sinatra::Base definiert werden.
|
881
1349
|
|
882
|
-
<tt>Sinatra::Base</tt> ist ein unbeschriebenes Blatt. Die meisten Optionen sind
|
1350
|
+
<tt>Sinatra::Base</tt> ist ein unbeschriebenes Blatt. Die meisten Optionen sind
|
1351
|
+
per default deaktiviert. Das betrifft auch den eingebauten Server. Siehe
|
1352
|
+
{Optionen und Konfiguration}[http://sinatra.github.com/configuration.html] für
|
1353
|
+
Details über mögliche Optionen.
|
1354
|
+
|
1355
|
+
=== Modularer vs. klassischer Stil
|
1356
|
+
|
1357
|
+
Entgegen häufiger Meinungen gibt es nichts gegen den klassischen Stil
|
1358
|
+
einzuwenden. Solange es die Applikation nicht beeinträchtigt, besteht kein
|
1359
|
+
Grund eine modulare Applikation zu erstellen.
|
1360
|
+
|
1361
|
+
Lediglich zwei Nachteile gegenüber dem modularen Stil sollten beachtet werden:
|
1362
|
+
|
1363
|
+
* Es kann nur eine Sinatra Applikation pro Ruby Prozess laufen. Sollten mehrere
|
1364
|
+
zum Einsatz kommen, muss auf modular umgestiegen werden.
|
1365
|
+
|
1366
|
+
* Der klassische Stil füllt Object mit Delegationsmethoden. Sollte die
|
1367
|
+
Applikation als gem/Bibliothek zum Einsatz kommen, sollte auf modular
|
1368
|
+
umgestiegen werden.
|
1369
|
+
|
1370
|
+
Es gibt keinen Grund, warum man modulare und klassische Elemente nicht
|
1371
|
+
vermischen sollte.
|
1372
|
+
|
1373
|
+
Will man jedoch von einem Stil auf den anderen umsteigen, sollten einige
|
1374
|
+
Unterschiede beachtet werden:
|
1375
|
+
|
1376
|
+
Szenario Classic Modular
|
1377
|
+
|
1378
|
+
app_file file loading sinatra nil
|
1379
|
+
run $0 == app_file false
|
1380
|
+
logging true false
|
1381
|
+
method_override true false
|
1382
|
+
inline_templates true false
|
1383
|
+
|
1384
|
+
|
1385
|
+
=== Eine modulare Applikation bereitstellen
|
1386
|
+
|
1387
|
+
Es gibt zwei übliche Wege eine modulare Anwendung zu starten. Zum einen über
|
1388
|
+
<tt>run!</tt>:
|
1389
|
+
|
1390
|
+
# mein_app.rb
|
1391
|
+
require 'sinatra/base'
|
1392
|
+
|
1393
|
+
class MeinApp < Sinatra::Base
|
1394
|
+
# ... Anwendungscode hierhin ...
|
1395
|
+
|
1396
|
+
# starte den Server, wenn die Ruby Datei direkt ausgeführt wird
|
1397
|
+
run! if app_file == $0
|
1398
|
+
end
|
1399
|
+
|
1400
|
+
Starte mit:
|
1401
|
+
|
1402
|
+
ruby mein_app.rb
|
1403
|
+
|
1404
|
+
Oder über eine <tt>config.ru</tt>, die es erlaubt irgendeinen Rack Handler zu
|
1405
|
+
verwenden:
|
1406
|
+
|
1407
|
+
# config.ru
|
1408
|
+
require 'mein_app'
|
1409
|
+
run MeineApp
|
1410
|
+
|
1411
|
+
Starte:
|
1412
|
+
|
1413
|
+
rackup -p 4567
|
1414
|
+
|
1415
|
+
=== Eine klassische Anwendung mit einer config.ru verwenden
|
1416
|
+
|
1417
|
+
Schreibe eine Anwendungsdatei:
|
1418
|
+
|
1419
|
+
# app.rb
|
1420
|
+
require 'sinatra'
|
1421
|
+
|
1422
|
+
get '/' do
|
1423
|
+
'Hallo Welt!'
|
1424
|
+
end
|
1425
|
+
|
1426
|
+
Sowie eine dazugehörige <tt>config.ru</tt>:
|
1427
|
+
|
1428
|
+
require 'app'
|
1429
|
+
run Sinatra::Application
|
1430
|
+
|
1431
|
+
=== Wann verwendet man eine config.ru?
|
1432
|
+
|
1433
|
+
Anzeichen dafür, dass man eine <tt>config.ru</tt> braucht:
|
1434
|
+
|
1435
|
+
* Man möchte einen anderen Rack Handler verwenden (Passenger, Unicorn,
|
1436
|
+
Heroku, ...).
|
1437
|
+
* Man möchte mehr als eine Subklasse von <tt>Sinatra::Base</tt>.
|
1438
|
+
* Man möchte Sinatra als Middleware verwenden, nicht als Endpoint.
|
1439
|
+
|
1440
|
+
<b>Es gibt keinen Grund eine <tt>config.ru</tt> zu verwenden, nur weil man eine
|
1441
|
+
Anwendung im modularen Stil betreiben möchte. Ebenso braucht man keine
|
1442
|
+
Anwendung im modularen Stil, um eine <tt>config.ru</tt> verwenden zu können.
|
1443
|
+
</b>
|
883
1444
|
|
884
1445
|
=== Sinatra als Middleware nutzen
|
885
1446
|
|
@@ -918,16 +1479,22 @@ Sinatra-Anwendung handen, es kann jede andere Rack-Anwendung sein
|
|
918
1479
|
get('/') { "Hallo #{session['user_name']}." }
|
919
1480
|
end
|
920
1481
|
|
921
|
-
==
|
1482
|
+
== Geltungsbereich und Bindung
|
922
1483
|
|
923
|
-
|
924
|
-
|
1484
|
+
Der Geltungsbereich (scope) legt fest, welche Methoden und Variablen zur
|
1485
|
+
Verfügung stehen.
|
925
1486
|
|
926
1487
|
=== Anwendungs- oder Klassenscope
|
927
1488
|
|
928
|
-
Jede Sinatra-Anwendung entspricht einer Sinatra::Base-Subklasse. Falls man die
|
1489
|
+
Jede Sinatra-Anwendung entspricht einer Sinatra::Base-Subklasse. Falls man die
|
1490
|
+
Top-Level-DSL verwendet (<tt>require 'sinatra'</tt>), so handelt es sich
|
1491
|
+
hierbei um Sinatra::Application, andernfalls is es jene Subklasse, die man
|
1492
|
+
explizit angelegt hat. Auf Klassenebene stehen Methoden wie +get+ oder +before+
|
1493
|
+
zur Verfügung, man hat aber keinen Zugriff auf das +request+-Object oder die
|
1494
|
+
+session+, da nur eine einzige Klasse für alle eingehenden Anfragen genutzt
|
1495
|
+
wird.
|
929
1496
|
|
930
|
-
Optionen die via
|
1497
|
+
Optionen die via +set+ gesetzt werden, sind Methoden auf Klassenebene:
|
931
1498
|
|
932
1499
|
class MyApp < Sinatra::Base
|
933
1500
|
# Hey, ich bin im Anwendungsscope!
|
@@ -943,18 +1510,22 @@ Im Anwendungsscope befindet man sich:
|
|
943
1510
|
|
944
1511
|
* In der Anwendungsklasse.
|
945
1512
|
* In Methoden die von Erweiterungen definiert werden.
|
946
|
-
* Im Block, der an
|
947
|
-
* In Procs und Blöcken die an
|
1513
|
+
* Im Block, der an +helpers+ übergeben wird.
|
1514
|
+
* In Procs und Blöcken die an +set+ übergeben werden.
|
948
1515
|
|
949
1516
|
Man kann auf das Scope-Object (die Klasse) wie folgt zugreifen:
|
950
1517
|
|
951
|
-
* Über das Objekt, dass an den
|
1518
|
+
* Über das Objekt, dass an den +configure+-Block übergeben wird (<tt>configure
|
952
1519
|
{ |c| ... }</tt>).
|
953
|
-
*
|
1520
|
+
* +settings+ aus den anderen Scopes heraus.
|
954
1521
|
|
955
1522
|
=== Anfrage- oder Instanzscope
|
956
1523
|
|
957
|
-
Für jede eingehende Anfrage wird eine neue Instanz der Anwendungsklasse
|
1524
|
+
Für jede eingehende Anfrage wird eine neue Instanz der Anwendungsklasse
|
1525
|
+
erstellt und alle Handlers werden in diesem Scope ausgeführt. Aus diesem Scope
|
1526
|
+
heraus kann man auf +request+ oder +session+ zugreifen und Methoden wie +erb+
|
1527
|
+
oder +haml+ aufrufen. Man kann mit der +settings+ Methode außerdem auf den
|
1528
|
+
Anwengungsscope zugreifen.
|
958
1529
|
|
959
1530
|
class MyApp < Sinatra::Base
|
960
1531
|
# Hey, ich bin im Anwendungsscope!
|
@@ -985,15 +1556,18 @@ weitergeleitet. Dieser verhält sich jedoch nicht 100%ig wie der Klassenscope,
|
|
985
1556
|
da man nicht die Bindung der Klasse besitzt: Nur Methoden, die explizit als
|
986
1557
|
delegierbar markiert wurden stehen hier zur Verfügung und man kann nicht auf
|
987
1558
|
die Variablen des Klassenscopes zugreifen (mit anderen Worten: man hat ein
|
988
|
-
anderes
|
1559
|
+
anderes +self+). Man kann mit <tt>Sinatra::Delegator.delegate
|
989
1560
|
:methoden_name</tt> auch weitere Delegationen hinzufügen.
|
990
1561
|
|
991
1562
|
Im Delegation-Scop befindet man sich:
|
992
1563
|
|
993
1564
|
* Im Top-Level, wenn man <tt>require 'sinatra'</tt> aufgerufen hat.
|
994
|
-
* In einem Objekt, dass mit dem
|
1565
|
+
* In einem Objekt, dass mit dem <tt>Sinatra::Delegator</tt> mixin erweitert wurde.
|
995
1566
|
|
996
|
-
Schau am besten im Code nach: Hier ist
|
1567
|
+
Schau am besten im Code nach: Hier ist
|
1568
|
+
{Sinatra::Delegator mixin}[http://github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb#L1064]
|
1569
|
+
definiert und wird in den
|
1570
|
+
{globalen Namespace eingebunden}[http://github.com/sinatra/sinatra/blob/master/lib/sinatra/main.rb#L25].
|
997
1571
|
|
998
1572
|
== Kommandozeile
|
999
1573
|
|
@@ -1011,7 +1585,40 @@ Die Optionen sind:
|
|
1011
1585
|
-x # Mutex lock einschalten (Standard ist off)
|
1012
1586
|
|
1013
1587
|
== Der neueste Stand (The Bleeding Edge)
|
1588
|
+
Um auf dem neusten Stand zu bleiben, kannst Du den Master Branch verwenden. Er
|
1589
|
+
sollte recht stabil sein. Ebenso gibt es von Zeit zu Zeit prerelease Gems, die
|
1590
|
+
du so installierst:
|
1591
|
+
|
1592
|
+
gem install sinatra --pre
|
1593
|
+
|
1594
|
+
=== Mit Bundler
|
1595
|
+
Wenn du deine App mit der neusten Version von Sinatra mit
|
1596
|
+
{Bundler}[http://gembundler.com/] nutzen willst, dann ist dies der
|
1597
|
+
vorgeschlagene Weg:
|
1598
|
+
|
1599
|
+
Soweit du Bundler noch nicht installiert hast, folgendes:
|
1600
|
+
|
1601
|
+
gem install bundler
|
1602
|
+
|
1603
|
+
Dann erstellst Du in deinem Projektverzeichnis eine sog. +Gemfile+ Datei mit
|
1604
|
+
folgendem Inhalt:
|
1605
|
+
|
1606
|
+
source :rubygems
|
1607
|
+
gem 'sinatra', :git => "git://github.com/sinatra/sinatra.git"
|
1608
|
+
|
1609
|
+
# evtl. andere Abhängigkeiten
|
1610
|
+
gem 'haml' # z.B. wenn du haml verwendest...
|
1611
|
+
gem 'activerecord', '~> 3.0' # ...oder ActiveRecord 3.x
|
1612
|
+
|
1613
|
+
Beachte: Du solltest hier alle Abhängigkeiten eintragen. Sinatras eigenen,
|
1614
|
+
direkten Abhängigkeiten (Tilt und Rack) werden von Bundler automatisch aus dem
|
1615
|
+
Gemfile von Sinatra hinzugefügt.
|
1616
|
+
|
1617
|
+
Jetzt kannst du deine App starten:
|
1014
1618
|
|
1619
|
+
bundle exec ruby myapp.rb
|
1620
|
+
|
1621
|
+
=== Eigenes Repository
|
1015
1622
|
Um auf den neuesten Stand von Sinatras Code zu sein, kann eine lokale Kopie
|
1016
1623
|
angelegt werden. Gestartet wird in der Anwendung mit dem <tt>sinatra/lib</tt>
|
1017
1624
|
Ordner im <tt>LOAD_PATH</tt>:
|
@@ -1036,11 +1643,28 @@ Um Sinatra Code von Zeit zu Zeit zu aktualisieren:
|
|
1036
1643
|
cd myproject/sinatra
|
1037
1644
|
git pull
|
1038
1645
|
|
1646
|
+
=== Gem erstellen
|
1647
|
+
|
1648
|
+
Aus der eigenen lokalen Kopie kann nun auch ein globales gem gebaut werden:
|
1649
|
+
|
1650
|
+
git clone git://github.com/sinatra/sinatra.git
|
1651
|
+
cd sinatra
|
1652
|
+
rake sinatra.gemspec
|
1653
|
+
rake install
|
1654
|
+
|
1655
|
+
Falls du normalerweise gems als root installierst, sollte die letzte Zeile
|
1656
|
+
so lauten:
|
1657
|
+
|
1658
|
+
sudo rake install
|
1659
|
+
|
1660
|
+
|
1661
|
+
|
1039
1662
|
== Mehr
|
1040
1663
|
|
1041
1664
|
* {Projekt Website}[http://sinatra.github.com/] - Ergänzende Dokumentation,
|
1042
1665
|
News und Links zu anderen Ressourcen.
|
1043
|
-
* {Hilfe beisteuern}[http://sinatra.github.com/contributing.html] - Einen
|
1666
|
+
* {Hilfe beisteuern}[http://sinatra.github.com/contributing.html] - Einen
|
1667
|
+
Fehler gefunden? Brauchst du Hilfe? Hast du einen Patch?
|
1044
1668
|
* {Issue Tracker}[http://github.com/sinatra/sinatra/issues]
|
1045
1669
|
* {Twitter}[http://twitter.com/sinatra]
|
1046
1670
|
* {Mailingliste}[http://groups.google.com/group/sinatrarb]
|