Permalink
Newer
Older
100644 2134 lines (1535 sloc) 67.5 KB
Melvin Lammerts
Jun 20, 2012
1
= Sinatra
2
<i>Attention : Ce document correspond à la traduction de la version anglaise et
3
il n'est peut être plus à jour.</i>
5
Sinatra est un DSL pour créer rapidement et facilement des applications web en
6
Ruby :
7
8
# mon_application.rb
9
require 'sinatra'
11
get '/' do
13
end
14
17
gem install sinatra
18
ruby -rubygems mon_application.rb
20
Le résultat est visible sur : http://localhost:4567
22
Il est recommandé d'exécuter également <tt>gem install thin</tt>, pour que
23
Sinatra utilise le server Thin quand il est disponible.
25
== Routes
26
27
Dans Sinatra, une route est une méthode HTTP couplée à un masque (pattern)
28
URL. Chaque route est associée à un bloc :
29
30
get '/' do
31
.. montrer quelque chose ..
32
end
33
34
post '/' do
35
.. créer quelque chose ..
36
end
37
38
put '/' do
39
.. remplacer quelque chose ..
40
end
41
42
patch '/' do
43
.. changer quelque chose ..
44
end
45
46
delete '/' do
47
.. effacer quelque chose ..
48
end
49
50
options '/' do
51
.. apaiser quelquechose ..
52
end
53
54
Les routes sont évaluées dans l'ordre où elles ont été définies. La première
55
route qui correspond à la requête est appelée.
57
Les masques peuvent inclure des paramètres nommés, accessibles par
58
l'intermédiaire du hash <tt>params</tt> :
59
60
get '/bonjour/:nom' do
61
# répond aux requêtes "GET /bonjour/foo" et "GET /bonjour/bar"
62
# params[:nom] est 'foo' ou 'bar'
64
end
65
66
Vous pouvez aussi accéder aux paramètres nommés directement grâce aux
67
paramètres du bloc comme ceci :
68
69
get '/bonjour/:nom' do |n|
71
end
72
73
Une route peut contenir un splat (caractère joker), accessible par
74
l'intermédiaire du tableau <tt>params[:splat]</tt> :
75
76
get '/dire/*/a/*' do
77
# répond à /dire/bonjour/a/monde
78
params[:splat] # => ["bonjour", "monde"]
79
end
80
81
get '/telecharger/*.*' do
82
# répond à /telecharger/chemin/vers/fichier.xml
83
params[:splat] # => ["chemin/vers/fichier", "xml"]
84
end
85
86
Ou par l'intermédiaire des paramètres du bloc :
87
88
get '/telecharger/*.*' do |chemin, ext|
89
[chemin, ext] # => ["path/to/file", "xml"]
90
end
91
92
Une route peut aussi être définie par une Expression Régulière :
93
94
get %r{/bonjour/([\w]+)} do
95
"Bonjour, #{params[:captures].first} !"
96
end
97
98
Là encore on peut utiliser les paramètres de bloc :
99
100
get %r{/bonjour/([\w]+)} do |c|
102
end
103
104
Les routes peuvent aussi comporter des paramètres optionnels :
105
106
get '/posts.?:format?' do
107
# répond à "GET /posts" et aussi à "GET /posts.json", "GET /posts.xml" etc...
108
end
109
110
A ce propos, à moins d'avoir désactivé la protection contre les attaques par
111
"path transversal" (voir plus loin), l'URL demandée peut avoir été modifiée
112
avant d'être comparée à vos routes.
113
116
Les routes peuvent définir toutes sortes de conditions, comme par exemple le
118
119
get '/foo', :agent => /Songbird (\d\.\d)[\d\/]*?/ do
120
"Vous utilisez Songbird version #{params[:agent][0]}"
121
end
122
123
get '/foo' do
124
# Correspond à tous les autres navigateurs
125
end
126
127
Les autres conditions disponibles sont +host_name+ et +provides+ :
128
129
get '/', :host_name => /^admin\./ do
130
"Zone Administrateur, Accès refusé !"
131
end
132
133
get '/', :provides => 'html' do
134
haml :index
135
end
136
137
get '/', :provides => ['rss', 'atom', 'xml'] do
138
builder :feed
139
end
140
141
Vous pouvez facilement définir vos propres conditions :
142
143
set(:probability) { |value| condition { rand <= value } }
144
145
get '/gagner_une_voiture', :probability => 0.1 do
147
end
148
149
get '/gagner_une_voiture' do
150
"Désolé, vous avez perdu."
151
end
152
153
Utilisez un splat (caractère joker) dans le cas d'une condition qui prend
154
plusieurs valeurs :
155
156
set(:auth) do |*roles| # <- ici on utilise un splat
157
condition do
158
unless logged_in? && roles.any? {|role| current_user.in_role? role }
159
redirect "/login/", 303
160
end
161
end
162
end
163
164
get "/mon/compte/", :auth => [:user, :admin] do
165
"Informations sur votre compte"
166
end
167
168
get "/reserve/aux/admins/", :auth => :admin do
169
"Seuls les administrateurs sont acceptés ici !"
170
end
171
174
La valeur renvoyée par le bloc correspondant à une route constitue le corps de
175
la réponse qui sera transmise au client HTTP ou du moins au prochain middleware
176
dans la pile Rack. Le plus souvent, il s'agit d'une chaîne de caractères,
177
comme dans les exemples précédents. Cependant, d'autres valeurs sont
178
acceptées.
179
180
Vous pouvez renvoyer n'importe quel objet qu'il s'agisse d'une réponse Rack
181
valide, d'un corps de réponse Rack ou d'un code statut HTTP :
183
* Un tableau de 3 éléments : <tt>[code statut (Fixnum), entêtes (Hash), corps
184
de la réponse (répondant à #each)]</tt>
185
* Un tableau de 2 élements : <tt>[code statut (Fixnum), corps de la réponse
186
(répondant à #each)]</tt>
187
* Un objet qui répond à <tt>#each</tt> et qui ne transmet que des chaînes de
188
caractères au bloc fourni
189
* Un Fixnum représentant le code statut
191
Avec cela, on peut facilement implémenter un streaming par exemple :
192
193
class Stream
194
def each
195
100.times { |i| yield "#{i}\n" }
196
end
197
end
198
199
get('/') { Stream.new }
200
201
Vous pouvez aussi utiliser le helper +stream+ (présenté un peu plus loin) pour
202
éviter la surcharge et intégrer le traitement relatif au streaming dans le bloc
203
de code de la route.
204
205
=== Masques de route spécifiques
206
207
Comme cela a été vu auparavant, Sinatra offre la possibilité d'utiliser des
208
masques sous forme de chaines de caractères ou des expressions régulières
209
pour définir les routes. Mais il est possible de faire bien plus. Vous pouvez
210
facilement définir vos propres masques :
211
212
class MasqueToutSauf
213
Masque = Struct.new(:captures)
214
215
def initialize(except)
216
@except = except
217
@captures = Masque.new([])
218
end
219
220
def match(str)
221
@caputres unless @except === str
222
end
223
end
224
225
def tout_sauf(masque)
226
MasqueToutSauf.new(masque)
227
end
228
229
get tout_sauf("/index") do
230
# ...
231
end
232
233
Notez que l'exemple ci-dessus est bien trop compliqué et que le même résultat
234
peut être obtenu avec :
235
236
get // do
237
pass if request.path_info == "/index"
238
# ...
239
end
240
241
Ou bien en utilisant la forme négative :
242
243
get %r{^(?!/index$)} do
244
# ...
245
end
246
249
Les fichiers du dossier <tt>./public</tt> sont servis de façon statique. Vous
250
avez la possibilité d'utiliser un autre répertoire en définissant le paramètre
251
<tt>:public_folder</tt> :
253
set :public_folder, File.dirname(__FILE__) + '/statique'
255
Notez que le nom du dossier public n'apparait pas dans l'URL. Le fichier
256
<tt>./public/css/style.css</tt> sera appelé via l'URL :
257
<tt>http://exemple.com/css/style.css</tt>.
258
259
Utilisez le paramètre <tt>:static_cache_control</tt> pour ajouter l'information
260
d'en-tête <tt>Cache-Control</tt> (voir plus loin).
261
262
== Vues / Templates
263
264
Chaqie langage de template est disponible via sa propre méthode de rendu,
265
lesquelles renvoient tout simplement une chaîne de caractères.
266
267
get '/' do
269
end
270
271
Ceci effectue le rendu de la vue <tt>views/index.erb</tt>.
273
Plutôt que d'utiliser le nom d'un template, vous pouvez directement passer
274
le contenu du template :
275
276
get '/' do
277
code = "<%= Time.now %>"
278
erb code
279
end
280
281
Les méthodes de templates acceptent un second paramètre, un hash d'options :
282
283
get '/' do
284
erb :index, :layout => :post
285
end
286
287
Ceci effectuera le rendu de la vue <tt>views/index.erb</tt> en l'intégrant
288
au +layout+ <tt>views/post.erb</tt> (les vues Erb sont intégrées par défaut
289
au +layout+ <tt>views/layout.erb</tt> quand ce fichier existe).
291
Toute option que Sinatra ne comprend pas sera passée au moteur de rendu :
292
293
get '/' do
294
haml :index, :format => :html5
295
end
296
297
Vous pouvez également définir des options par langage de template de façon
298
générale :
300
set :haml, :format => html5
301
302
get '/' do
304
end
305
306
Les options passées à la méthode de rendu prennent le pas sur les options
307
définies au moyen de +set+.
309
Options disponibles :
311
[locals]
312
Liste de variables locales passées au document. Pratique pour les vues
313
partielles.
314
Exemple : <tt>erb "<%= foo %>", :locals => {:foo => "bar"}</tt>.
316
[default_encoding]
317
Encodage de caractères à utiliser en cas d'incertitude. Par défaut, c'est
318
<tt>settings.default_encoding</tt>.
320
[views]
321
Dossier de vues dans lequel chercher les templates. Par défaut
322
<tt>settings.views</tt>.
324
[layout]
325
S'il faut ou non utiliser un +layout+ (+true+ or +false+). Indique le
326
template à utiliser lorsque c'est un symbole. Exemple : <tt>erb :index,
327
:layout => !request.xhr?</tt>.
329
[content_type]
330
Content-Type que le template produit, dépend par défaut du langage de
331
template.
333
[scope]
334
Contexte sous lequel effectuer le rendu du template. Par défaut il s'agit
335
de l'instance de l'application. Si vous changez cela, les variables
336
d'instance et les méthodes utilitaires ne seront pas disponibles.
338
[layout_engine]
339
Moteur de rendu à utiliser pour le +layout+. Utile pour les langages ne
340
supportant pas les +layouts+. Il s'agit par défaut du moteur utilisé pour
341
le rendu du template. Exemple : <tt>set :rdoc, :layout_engine => :erb</tt>
343
Les templates sont supposés se trouver directement dans le dossier
344
<tt>./views</tt>. Pour utiliser un dossier de vues différent :
346
set :views, settings.root + '/templates'
348
Il est important de se souvenir que les templates sont toujours référencés
349
sous forme de symboles, même lorsqu'ils sont dans un sous-répertoire (dans
350
ce cas, utilisez <tt>:'sous_repertoire/template'</tt>). Il faut utiliser
351
un symbole car les méthodes de rendu évaluent le contenu des chaînes de
352
caractères au lieu de les considérer comme un chemin vers un fichier.
354
=== Langages de template disponibles
356
Certains langages ont plusieurs implémentations. Pour préciser l'implémentation
357
à utiliser (et garantir l'aspect thread-safe), vous devez simplement l'avoir
358
chargée au préalable :
360
require 'rdiscount' # ou require 'bluecloth'
361
get('/') { markdown :index }
363
=== Templates Haml
365
Dépendances:: {haml}[http://haml.info/]
366
Extensions de fichier:: <tt>.haml</tt>
367
Exemple:: <tt>haml :index, :format => :html5</tt>
369
=== Templates Erb
371
Dépendances:: {erubis}[http://www.kuwata-lab.com/erubis/] ou
372
erb (inclus avec Ruby)
373
Extensions de fichier:: <tt>.erb</tt>, <tt>.rhtml</tt> ou <tt>.erubis</tt>
374
(Erubis seulement)
375
Exemple:: <tt>erb :index</tt>
377
=== Templates Builder
379
Dépendances:: {builder}[http://builder.rubyforge.org/]
380
Extensions de fichier:: <tt>.builder</tt>
381
Exemple:: <tt>builder { |xml| xml.em "salut" }</tt>
383
Ce moteur accepte également un bloc pour des templates en ligne (voir exemple).
385
=== Templates Nokogiri
387
Dépendances:: {nokogiri}[http://nokogiri.org/]
388
Extensions de fichier:: <tt>.nokogiri</tt>
389
Exemple:: <tt>nokogiri { |xml| xml.em "salut" }</tt>
391
Ce moteur accepte également un bloc pour des templates en ligne (voir exemple).
393
=== Templates Sass
395
Dépendances:: {sass}[http://sass-lang.com/]
396
Extensions de fichier:: <tt>.sass</tt>
397
Exemple:: <tt>sass :stylesheet, :style => :expanded</tt>
399
=== Templates SCSS
401
Dépendances:: {sass}[http://sass-lang.com/]
402
Extensions de fichier:: <tt>.scss</tt>
403
Exemple:: <tt>scss :stylesheet, :style => :expanded</tt>
405
=== Templates Less
407
Dépendances:: {less}[http://www.lesscss.org/]
408
Extensions de fichier:: <tt>.less</tt>
409
Exemple:: <tt>less :stylesheet</tt>
413
Dépendances:: {liquid}[http://www.liquidmarkup.org/]
414
Extensions de fichier:: <tt>.liquid</tt>
415
Exemple:: <tt>liquid :index, :locals => { :key => 'value' }</tt>
417
Comme vous ne pouvez appeler de méthodes Ruby (autres que +yield+) dans un
418
template Liquid, vous aurez sûrement à lui passer des variables locales.
422
Dépendances:: {rdiscount}[https://github.com/rtomayko/rdiscount],
423
{redcarpet}[https://github.com/tanoku/redcarpet],
424
{bluecloth}[http://deveiate.org/projects/BlueCloth],
425
{kramdown}[http://kramdown.rubyforge.org/] *ou*
426
{maruku}[http://maruku.rubyforge.org/]
427
Extensions de fichier:: <tt>.markdown</tt>, <tt>.mkd</tt> et <tt>.md</tt>
428
Exemple:: <tt>markdown :index, :layout_engine => :erb</tt>
430
Il n'est pas possible d'appeler des méthodes depuis markdown, ni de lui
431
passer des variables locales. Par conséquent, il sera souvent utilisé en
432
combinaison avec un autre moteur de rendu :
434
erb :overview, :locals => { :text => markdown(:introduction) }
436
Notez que vous pouvez également appeler la méthode +markdown+ au sein d'autres
439
%h1 Hello From Haml !
440
%p= markdown(:greetings)
442
Comme vous ne pouvez pas appeler de Ruby au sein de Markdown, vous ne pouvez
443
pas utiliser de +layouts+ écrits en Markdown. Toutefois, il est possible
444
d'utiliser un moteur de rendu différent pour le template et pour le +layout+
445
en utilisant l'option <tt>:layout_engine</tt>.
449
Dépendances:: {RedCloth}[http://redcloth.org/]
450
Extensions de fichier:: <tt>.textile</tt>
451
Exemple:: <tt>textile :index, :layout_engine => :erb</tt>
453
Il n'est pas possible d'appeler des méthodes depuis textile, ni de lui
454
passer des variables locales. Par conséquent, il sera souvent utilisé en
455
combinaison avec un autre moteur de rendu :
457
erb :overview, :locals => { :text => textile(:introduction) }
459
Notez que vous pouvez également appeler la méthode +textile+ au sein d'autres
462
%h1 Hello From Haml !
463
%p= textile(:greetings)
465
Comme vous ne pouvez pas appeler de Ruby au sein de Textile, vous ne pouvez
466
pas utiliser de +layouts+ écrits en Textile. Toutefois, il est possible
467
d'utiliser un moteur de rendu différent pour le template et pour le +layout+
468
en utilisant l'option <tt>:layout_engine</tt>.
472
Dépendances:: {rdoc}[http://rdoc.rubyforge.org/]
473
Extensions de fichier:: <tt>.rdoc</tt>
474
Exemple:: <tt>rdoc :README, :layout_engine => :erb</tt>
476
Il n'est pas possible d'appeler des méthodes depuis rdoc, ni de lui
477
passer des variables locales. Par conséquent, il sera souvent utilisé en
478
combinaison avec un autre moteur de rendu :
480
erb :overview, :locals => { :text => rdoc(:introduction) }
482
Notez que vous pouvez également appeler la méthode +rdoc+ au sein d'autres
485
%h1 Hello From Haml !
486
%p= rdoc(:greetings)
488
Comme vous ne pouvez pas appeler de Ruby au sein de RDoc, vous ne pouvez
489
pas utiliser de +layouts+ écrits en RDoc. Toutefois, il est possible
490
d'utiliser un moteur de rendu différent pour le template et pour le +layout+
491
en utilisant l'option <tt>:layout_engine</tt>.
495
Dépendances:: {radius}[http://radius.rubyforge.org/]
496
Extensions de fichier:: <tt>.radius</tt>
497
Exemple:: <tt>radius :index, :locals => { :key => 'value' }</tt>
499
Comme vous ne pouvez pas appeler de méthodes Ruby depuis un template Radius,
500
vous aurez sûrement à lui passer des variables locales.
504
Dépendances:: {markaby}[http://markaby.github.com/]
505
Extensions de fichier:: <tt>.mab</tt>
506
Exemple:: <tt>markaby { h1 "Bienvenue !" }</tt>
508
Ce moteur accepte également un bloc pour des templates en ligne (voir exemple).
510
=== Templates RABL
511
512
Dépendances:: {rabl}[https://github.com/nesquena/rabl]
513
Extensions de fichier:: <tt>.rabl</tt>
514
Exemple:: <tt>rabl :index</tt>
515
516
=== Templates Slim
517
518
Dépendances:: {slim}[http://slim-lang.com/]
519
Extensions de fichier:: <tt>.slim</tt>
520
Exemple:: <tt>slim :index</tt>
522
=== Templates Creole
523
524
Dépendances:: {creole}[https://github.com/minad/creole]
525
Extensions de fichier:: <tt>.creole</tt>
526
Exemple:: <tt>creole :wiki, :layout_engine => :erb</tt>
528
Il n'est pas possible d'appeler des méthodes depuis creole, ni de lui
529
passer des variables locales. Par conséquent, il sera souvent utilisé en
530
combinaison avec un autre moteur de rendu :
532
erb :overview, :locals => { :text => creole(:introduction) }
534
Notez que vous pouvez également appeler la méthode +creole+ au sein d'autres
535
templates :
537
%h1 Hello From Haml !
538
%p= creole(:greetings)
540
Comme vous ne pouvez pas appeler de Ruby au sein de Creole, vous ne pouvez
541
pas utiliser de +layouts+ écrits en Creole. Toutefois, il est possible
542
d'utiliser un moteur de rendu différent pour le template et pour le +layout+
543
en utilisant l'option <tt>:layout_engine</tt>.
545
=== Templates CoffeeScript
547
Dépendances:: {coffee-script}[https://github.com/josh/ruby-coffee-script]
548
et un {moyen d'exécuter javascript}[https://github.com/sstephenson/execjs/blob/master/README.md#readme]
549
Extensions de fichier:: <tt>.coffee</tt>
550
Exemple:: <tt>coffee :index</tt>
552
=== Templates Yajl
553
554
Dépendances:: {yajl-ruby}[https://github.com/brianmario/yajl-ruby]
555
Extensions de fichier:: <tt>.yajl</tt>
556
Exemple:: <tt>yajl :index, :locals => { :key => 'qux' }, :callback => 'present', :variable => 'resource'</tt>
557
558
Le source du template est évalué en tant que chaine Ruby, puis la variable json
559
obtenue est convertie avec #to_json.
560
561
json = { :foo => 'bar' }
562
json[:baz] = key
563
564
Les options <tt>:callback</tt> et <tt>:variable</tt> peuvent être utilisées
565
pour décorer l'objet retourné.
566
567
var resource = {"foo":"bar","baz":"qux"}; present(resource);
568
569
=== Templates WLang
570
571
Dependency:: {wlang}[https://github.com/blambeau/wlang/]
572
File Extensions:: <tt>.wlang</tt>
573
Example:: <tt>wlang :index, :locals => { :key => 'value' }</tt>
574
575
L'appel de code ruby au sein des templates n'est pas idiomatique en wlang. L'écriture de
576
templates sans logique est encouragé, via le passage de variables locales. Il est néanmoins
577
possible d'écrire un +layout+ en wlang et d'y utiliser +yield+.
578
579
=== Templates embarqués
580
581
get '/' do
582
haml '%div.title Bonjour le monde'
583
end
584
585
Générera le code du template spécifié dans la chaîne de caractères.
586
587
=== Accéder aux variables dans un Template
588
589
Un template est évalué dans le même contexte que l'endroit d'où il a été
590
appelé (gestionnaire de route). Les variables d'instance déclarées dans le
591
gestionnaire de route sont directement accessibles dans le template :
592
593
get '/:id' do
594
@foo = Foo.find(params[:id])
595
haml '%h1= @foo.nom'
596
end
597
598
Alternativement, on peut passer un hash contenant des variables locales :
599
600
get '/:id' do
601
foo = Foo.find(params[:id])
602
haml '%h1= foo.nom', :locals => { :foo => foo }
603
end
604
605
Ceci est généralement utilisé lorsque l'on veut utiliser un template comme
606
partiel (depuis un autre template) et qu'il est donc nécessaire d'adapter les
607
noms de variables.
608
609
=== Templates dans le fichier source
610
611
Des templates peuvent être définis dans le fichier source comme ceci :
612
613
require 'sinatra'
614
615
get '/' do
616
haml :index
617
end
618
619
__END__
620
621
@@ layout
622
%html
623
= yield
624
625
@@ index
628
NOTE : Les templates du fichier source qui contient <tt>require 'sinatra'</tt>
629
sont automatiquement chargés. Si vous avez des templates dans d'autres
630
fichiers source, il faut explicitement les déclarer avec
631
<tt>enable :inline_templates</tt>.
635
Les templates peuvent aussi être définis grâce à la méthode de haut niveau
637
638
template :layout do
639
"%html\n =yield\n"
640
end
641
642
template :index do
644
end
645
646
get '/' do
647
haml :index
648
end
649
650
Si un template nommé "layout" existe, il sera utilisé à chaque fois qu'un
651
template sera affiché. Vous pouvez désactivez les layouts au cas par cas en
652
passant <tt>:layout => false</tt> ou bien les désactiver par défaut au moyen
653
de <tt>set :haml, :layout => false</tt> :
654
655
get '/' do
656
haml :index, :layout => !request.xhr?
657
end
658
659
=== Associer des extensions de fichier
660
661
Pour associer une extension de fichier avec un moteur de rendu, utilisez
662
<tt>Tilt.register</tt>. Par exemple, si vous désirez utiliser l'extension
663
de fichier +tt+ pour les templates Textile, vous pouvez faire comme suit :
665
Tilt.register :tt, Tilt[:textile]
666
667
=== Ajouter son propre moteur de rendu
668
669
En premier lieu, déclarez votre moteur de rendu avec Tilt, ensuite créez
670
votre méthode de rendu :
671
672
Tilt.register :monmoteur, MonMerveilleurMoteurDeRendu
673
674
helpers do
675
def monmoteur(*args) render(:monmoteur, *args) end
676
end
677
678
get '/' do
679
monmoteur :index
680
end
681
682
Utilisera <tt>./views/index.monmoteur</tt>. Voir
683
https://github.com/rtomayko/tilt pour en savoir plus sur Tilt.
684
685
== Filtres
686
687
Les filtres before sont exécutés avant chaque requête, dans le même contexte
688
que les routes, et permettent de modifier la requête et sa réponse. Les
689
variables d'instance déclarées dans les filtres sont accessibles au niveau
690
des routes et des templates :
691
692
before do
694
request.path_info = '/foo/bar/baz'
695
end
696
697
get '/foo/*' do
699
params[:splat] #=> 'bar/baz'
700
end
701
702
Les filtres after sont exécutés après chaque requête à l'intérieur du même
703
contexte et permettent de modifier la requête et sa réponse. Les variables
704
d'instance déclarées dans les filtres before ou les routes sont accessibles
705
au niveau des filtres after :
706
707
after do
708
puts response.status
709
end
710
711
Note : Le corps de la réponse n'est pas disponible au niveau du filtre after
712
car il ne sera généré que plus tard (sauf dans le cas où vous utilisez la
713
méthode +body+ au lieu de simplement renvoyer une chaine depuis vos routes).
715
Les filtres peuvent être associés à un masque, ce qui permet de limiter leur
716
exécution aux cas où la requête correspond à ce masque :
717
718
before '/secret/*' do
719
authentification!
720
end
721
722
after '/faire/:travail' do |travail|
723
session[:dernier_travail] = travail
724
end
725
726
Tout comme les routes, les filtres acceptent également des conditions :
727
728
before :agent => /Songbird/ do
729
# ...
730
end
731
732
after '/blog/*', :host_name => 'example.com' do
733
# ...
734
end
735
736
== Helpers
737
738
Utilisez la méthode de haut niveau <tt>helpers</tt> pour définir des routines
739
qui seront accessibles dans vos gestionnaires de route et dans vos templates :
740
741
helpers do
742
def bar(nom)
743
"#{nom}bar"
744
end
745
end
746
747
get '/:nom' do
748
bar(params[:nom])
749
end
750
751
Vous pouvez aussi définir les méthodes helper dans un module séparé :
752
753
module FooUtils
754
def foo(nom) "#{nom}foo" end
755
end
756
757
module BarUtils
758
def bar(nom) "#{nom}bar" end
759
end
760
761
helpers FooUtils, BarUtils
762
763
Cela a le même résultat que d'inclure les modules dans la classe de
764
l'application.
765
766
=== Utiliser les sessions
767
768
Une session est utilisée pour conserver un état entre les requêtes. Une fois
769
activées, vous avez un +hash+ de session par session utilisateur :
770
771
enable :sessions
772
773
get '/' do
774
"valeur = " << session[:valeur].inspect
775
end
776
777
get '/:value' do
778
session[:valeur] = params[:valeur]
779
end
780
781
Notez que <tt>enable :sessions</tt> enregistre en fait toutes les données dans
782
un +cookie+. Ce n'est pas toujours ce que vous voulez (enregistrer beaucoup de
783
données va augmenter le traffic par exemple). Vous pouvez utiliser n'importe
784
quel +middleware+ Rack de session afin d'éviter cela. N'utiliser *pas*
785
<tt>enable :sessions</tt> dans ce cas mais charger le +middleware+ de votre
786
choix comme vous le feriez pour n'importe quel autre +middleware+ :
787
788
use Rack::Session::Pool, :expire_after => 2592000
789
790
get '/' do
791
"valeur = " << session[:valeur].inspect
792
end
793
794
get '/:value' do
795
session[:valeur] = params[:valeur]
796
end
797
798
Pour renforcer la sécurité, les données de session dans le cookie sont signées
799
avec une clé secrète de session. Une clé secrète est générée pour vous au
800
hasard par Sinatra. Toutefois, comme cette clé change à chaque démarrage de
801
votre application, vous pouvez définir cette clé vous-même afin que toutes
802
les instances de votre application la partage :
803
804
set :session_secret, 'super secret'
805
806
Si vous souhaitez avoir plus de contrôle, vous pouvez également enregistrer un
807
+hash+ avec des options lors de la configuration de +sessions+ :
808
809
set :sessions, :domain => 'foo.com'
810
811
=== Halt
813
Pour arrêter immédiatement la requête dans un filtre ou un gestionnaire de
815
816
halt
817