~l3on/ubuntu/precise/ruby-sinatra/version-for-843734

« back to all changes in this revision

Viewing changes to README.rdoc

  • Committer: Bazaar Package Importer
  • Author(s): Lucas Nussbaum
  • Date: 2011-04-26 15:41:55 UTC
  • Revision ID: james.westby@ubuntu.com-20110426154155-vn2r1ery5rj8249b
Tags: upstream-1.2.3
ImportĀ upstreamĀ versionĀ 1.2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
= Sinatra
 
2
 
 
3
Sinatra is a DSL for quickly creating web applications in Ruby with minimal
 
4
effort:
 
5
 
 
6
  # myapp.rb
 
7
  require 'sinatra'
 
8
  
 
9
  get '/' do
 
10
    'Hello world!'
 
11
  end
 
12
 
 
13
Install the gem and run with:
 
14
 
 
15
  gem install sinatra
 
16
  ruby -rubygems myapp.rb
 
17
 
 
18
View at: http://localhost:4567
 
19
 
 
20
It is recommended to also run <tt>gem install thin</tt>, which Sinatra will
 
21
pick up if available.
 
22
 
 
23
== Routes
 
24
 
 
25
In Sinatra, a route is an HTTP method paired with a URL-matching pattern.
 
26
Each route is associated with a block:
 
27
 
 
28
  get '/' do
 
29
    .. show something ..
 
30
  end
 
31
 
 
32
  post '/' do
 
33
    .. create something ..
 
34
  end
 
35
 
 
36
  put '/' do
 
37
    .. update something ..
 
38
  end
 
39
 
 
40
  delete '/' do
 
41
    .. annihilate something ..
 
42
  end
 
43
  
 
44
  options '/' do
 
45
    .. appease something ..
 
46
  end
 
47
 
 
48
Routes are matched in the order they are defined. The first route that
 
49
matches the request is invoked.
 
50
 
 
51
Route patterns may include named parameters, accessible via the
 
52
<tt>params</tt> hash:
 
53
 
 
54
  get '/hello/:name' do
 
55
    # matches "GET /hello/foo" and "GET /hello/bar"
 
56
    # params[:name] is 'foo' or 'bar'
 
57
    "Hello #{params[:name]}!"
 
58
  end
 
59
 
 
60
You can also access named parameters via block parameters:
 
61
 
 
62
  get '/hello/:name' do |n|
 
63
    "Hello #{n}!"
 
64
  end
 
65
 
 
66
Route patterns may also include splat (or wildcard) parameters, accessible
 
67
via the <tt>params[:splat]</tt> array:
 
68
 
 
69
  get '/say/*/to/*' do
 
70
    # matches /say/hello/to/world
 
71
    params[:splat] # => ["hello", "world"]
 
72
  end
 
73
 
 
74
  get '/download/*.*' do
 
75
    # matches /download/path/to/file.xml
 
76
    params[:splat] # => ["path/to/file", "xml"]
 
77
  end
 
78
 
 
79
Route matching with Regular Expressions:
 
80
 
 
81
  get %r{/hello/([\w]+)} do
 
82
    "Hello, #{params[:captures].first}!"
 
83
  end
 
84
 
 
85
Or with a block parameter:
 
86
 
 
87
  get %r{/hello/([\w]+)} do |c|
 
88
    "Hello, #{c}!"
 
89
  end
 
90
 
 
91
=== Conditions
 
92
 
 
93
Routes may include a variety of matching conditions, such as the user agent:
 
94
 
 
95
  get '/foo', :agent => /Songbird (\d\.\d)[\d\/]*?/ do
 
96
    "You're using Songbird version #{params[:agent][0]}"
 
97
  end
 
98
 
 
99
  get '/foo' do
 
100
    # Matches non-songbird browsers
 
101
  end
 
102
 
 
103
Other available conditions are +host_name+ and +provides+:
 
104
 
 
105
  get '/', :host_name => /^admin\./ do
 
106
    "Admin Area, Access denied!"
 
107
  end
 
108
 
 
109
  get '/', :provides => 'html' do
 
110
    haml :index
 
111
  end
 
112
  
 
113
  get '/', :provides => ['rss', 'atom', 'xml'] do
 
114
    builder :feed
 
115
  end
 
116
 
 
117
You can easily define your own conditions:
 
118
 
 
119
  set(:probability) { |value| condition { rand <= value } }
 
120
  
 
121
  get '/win_a_car', :probability => 0.1 do
 
122
    "You won!"
 
123
  end
 
124
  
 
125
  get '/win_a_car' do
 
126
    "Sorry, you lost."
 
127
  end
 
128
 
 
129
=== Return Values
 
130
 
 
131
The return value of a route block determines at least the response body passed
 
132
on to the HTTP client, or at least the next middleware in the Rack stack.
 
133
Most commonly, this is a string, as in the above examples. But other values are
 
134
also accepted.
 
135
 
 
136
You can return any object that would either be a valid Rack response, Rack
 
137
body object or HTTP status code:
 
138
 
 
139
* An Array with three elements: <tt>[status (Fixnum), headers (Hash), response body (responds to #each)]</tt>
 
140
* An Array with two elements: <tt>[status (Fixnum), response body (responds to #each)]</tt>
 
141
* An object that responds to <tt>#each</tt> and passes nothing but strings to the given block
 
142
* A Fixnum representing the status code
 
143
 
 
144
That way we can, for instance, easily implement a streaming example:
 
145
 
 
146
    class Stream
 
147
      def each
 
148
        100.times { |i| yield "#{i}\n" }
 
149
      end
 
150
    end
 
151
 
 
152
    get('/') { Stream.new }
 
153
 
 
154
=== Custom Route Matchers
 
155
 
 
156
As shown above, Sinatra ships with built-in support for using String patterns
 
157
and regular expressions as route matches. However, it does not stop there. You
 
158
can easily define your own matchers:
 
159
 
 
160
  class AllButPattern
 
161
    Match = Struct.new(:captures)
 
162
 
 
163
    def initialize(except)
 
164
      @except   = except
 
165
      @captures = Match.new([])
 
166
    end
 
167
 
 
168
    def match(str)
 
169
      @captures unless @except === str
 
170
    end
 
171
  end
 
172
 
 
173
  def all_but(pattern)
 
174
    AllButPattern.new(pattern)
 
175
  end
 
176
 
 
177
  get all_but("/index") do
 
178
    # ...
 
179
  end
 
180
 
 
181
Note that the above example might be over-engineered, as it can also be
 
182
expressed as:
 
183
 
 
184
  get // do
 
185
    pass if request.path_info == "/index"
 
186
    # ...
 
187
  end
 
188
 
 
189
Or, using negative look ahead:
 
190
 
 
191
  get %r{^(?!/index$)} do
 
192
    # ...
 
193
  end
 
194
 
 
195
== Static Files
 
196
 
 
197
Static files are served from the <tt>./public</tt> directory. You can specify
 
198
a different location by setting the <tt>:public</tt> option:
 
199
 
 
200
  set :public, File.dirname(__FILE__) + '/static'
 
201
 
 
202
Note that the public directory name is not included in the URL. A file
 
203
<tt>./public/css/style.css</tt> is made available as
 
204
<tt>http://example.com/css/style.css</tt>.
 
205
 
 
206
== Views / Templates
 
207
 
 
208
Templates are assumed to be located directly under the <tt>./views</tt>
 
209
directory. To use a different views directory:
 
210
 
 
211
  set :views, File.dirname(__FILE__) + '/templates'
 
212
 
 
213
One important thing to remember is that you always have to reference
 
214
templates with symbols, even if they're in a subdirectory (in this
 
215
case, use <tt>:'subdir/template'</tt>). You must use a symbol because
 
216
otherwise rendering methods will render any strings passed to them
 
217
directly.
 
218
 
 
219
=== Haml Templates
 
220
 
 
221
The <tt>haml</tt> gem/library is required to render HAML templates:
 
222
 
 
223
  # You'll need to require haml in your app
 
224
  require 'haml'
 
225
 
 
226
  get '/' do
 
227
    haml :index
 
228
  end
 
229
 
 
230
Renders <tt>./views/index.haml</tt>.
 
231
 
 
232
{Haml's options}[http://haml-lang.com/docs/yardoc/file.HAML_REFERENCE.html#options]
 
233
can be set globally through Sinatra's configurations,
 
234
see {Options and Configurations}[http://www.sinatrarb.com/configuration.html],
 
235
and overridden on an individual basis.
 
236
 
 
237
  set :haml, :format => :html5 # default Haml format is :xhtml
 
238
 
 
239
  get '/' do
 
240
    haml :index, :format => :html4 # overridden
 
241
  end
 
242
 
 
243
 
 
244
=== Erb Templates
 
245
 
 
246
  # You'll need to require erb in your app
 
247
  require 'erb'
 
248
 
 
249
  get '/' do
 
250
    erb :index
 
251
  end
 
252
 
 
253
Renders <tt>./views/index.erb</tt>.
 
254
 
 
255
=== Erubis Templates
 
256
 
 
257
The <tt>erubis</tt> gem/library is required to render Erubis templates:
 
258
 
 
259
  # You'll need to require erubis in your app
 
260
  require 'erubis'
 
261
 
 
262
  get '/' do
 
263
    erubis :index
 
264
  end
 
265
 
 
266
Renders <tt>./views/index.erubis</tt>.
 
267
 
 
268
It is also possible to replace Erb with Erubis:
 
269
 
 
270
  require 'erubis'
 
271
  Tilt.register :erb, Tilt[:erubis]
 
272
  
 
273
  get '/' do
 
274
    erb :index
 
275
  end
 
276
 
 
277
Renders <tt>./views/index.erb</tt> with Erubis.
 
278
 
 
279
=== Builder Templates
 
280
 
 
281
The <tt>builder</tt> gem/library is required to render builder templates:
 
282
 
 
283
  # You'll need to require builder in your app
 
284
  require 'builder'
 
285
 
 
286
  get '/' do
 
287
    builder :index
 
288
  end
 
289
 
 
290
Renders <tt>./views/index.builder</tt>.
 
291
 
 
292
=== Nokogiri Templates
 
293
 
 
294
The <tt>nokogiri</tt> gem/library is required to render nokogiri templates:
 
295
 
 
296
  # You'll need to require nokogiri in your app
 
297
  require 'nokogiri'
 
298
 
 
299
  get '/' do
 
300
    nokogiri :index
 
301
  end
 
302
 
 
303
Renders <tt>./views/index.nokogiri</tt>.
 
304
 
 
305
=== Sass Templates
 
306
 
 
307
The <tt>haml</tt> or <tt>sass</tt> gem/library is required to render Sass templates:
 
308
 
 
309
  # You'll need to require haml or sass in your app
 
310
  require 'sass'
 
311
 
 
312
  get '/stylesheet.css' do
 
313
    sass :stylesheet
 
314
  end
 
315
 
 
316
Renders <tt>./views/stylesheet.sass</tt>.
 
317
 
 
318
{Sass's options}[http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#options]
 
319
can be set globally through Sinatra's configurations,
 
320
see {Options and Configurations}[http://www.sinatrarb.com/configuration.html],
 
321
and overridden on an individual basis.
 
322
 
 
323
  set :sass, :style => :compact # default Sass style is :nested
 
324
 
 
325
  get '/stylesheet.css' do
 
326
    sass :stylesheet, :style => :expanded # overridden
 
327
  end
 
328
 
 
329
=== Scss Templates
 
330
 
 
331
The <tt>haml</tt> or <tt>sass</tt> gem/library is required to render Scss templates:
 
332
 
 
333
  # You'll need to require haml or sass in your app
 
334
  require 'sass'
 
335
 
 
336
  get '/stylesheet.css' do
 
337
    scss :stylesheet
 
338
  end
 
339
 
 
340
Renders <tt>./views/stylesheet.scss</tt>.
 
341
 
 
342
{Scss's options}[http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#options]
 
343
can be set globally through Sinatra's configurations,
 
344
see {Options and Configurations}[http://www.sinatrarb.com/configuration.html],
 
345
and overridden on an individual basis.
 
346
 
 
347
  set :scss, :style => :compact # default Scss style is :nested
 
348
 
 
349
  get '/stylesheet.css' do
 
350
    scss :stylesheet, :style => :expanded # overridden
 
351
  end
 
352
 
 
353
=== Less Templates
 
354
 
 
355
The <tt>less</tt> gem/library is required to render Less templates:
 
356
 
 
357
  # You'll need to require less in your app
 
358
  require 'less'
 
359
 
 
360
  get '/stylesheet.css' do
 
361
    less :stylesheet
 
362
  end
 
363
 
 
364
Renders <tt>./views/stylesheet.less</tt>.
 
365
 
 
366
=== Liquid Templates
 
367
 
 
368
The <tt>liquid</tt> gem/library is required to render Liquid templates:
 
369
 
 
370
  # You'll need to require liquid in your app
 
371
  require 'liquid'
 
372
 
 
373
  get '/' do
 
374
    liquid :index
 
375
  end
 
376
 
 
377
Renders <tt>./views/index.liquid</tt>.
 
378
 
 
379
Since you cannot call Ruby methods (except for +yield+) from a Liquid
 
380
template, you almost always want to pass locals to it:
 
381
 
 
382
  liquid :index, :locals => { :key => 'value' }
 
383
 
 
384
=== Markdown Templates
 
385
 
 
386
The <tt>rdiscount</tt> gem/library is required to render Markdown templates:
 
387
 
 
388
  # You'll need to require rdiscount in your app
 
389
  require "rdiscount"
 
390
  
 
391
  get '/' do
 
392
    markdown :index
 
393
  end
 
394
 
 
395
Renders <tt>./views/index.markdown</tt> (+md+ and +mkd+ are also valid file
 
396
extensions).
 
397
 
 
398
It is not possible to call methods from markdown, nor to pass locals to it.
 
399
You therefore will usually use it in combination with another rendering
 
400
engine:
 
401
 
 
402
  erb :overview, :locals => { :text => markdown(:introduction) }
 
403
 
 
404
Note that you may also call the +markdown+ method from within other templates:
 
405
 
 
406
  %h1 Hello From Haml!
 
407
  %p= markdown(:greetings)
 
408
 
 
409
Since you cannot call Ruby from Markdown, you cannot use layouts written in
 
410
Markdown. However, it is possible to use another rendering engine for the
 
411
template than for the layout by passing the <tt>:layout_engine</tt> option:
 
412
 
 
413
  get '/' do
 
414
    markdown :index, :layout_engine => :erb
 
415
  end
 
416
 
 
417
This will render <tt>./views/index.md</tt> with <tt>./views/layout.erb</tt> as
 
418
layout.
 
419
 
 
420
Remember that you can set such rendering options globally:
 
421
 
 
422
  set :markdown, :layout_engine => :haml, :layout => :post
 
423
 
 
424
  get '/' do
 
425
    markdown :index
 
426
  end
 
427
 
 
428
This will render <tt>./views/index.md</tt> (and any other Markdown template)
 
429
with <tt>./views/post.haml</tt> as layout.
 
430
 
 
431
It is also possible to parse Markdown with BlueCloth rather than RDiscount:
 
432
 
 
433
  require 'bluecloth'
 
434
  
 
435
  Tilt.register 'markdown', BlueClothTemplate
 
436
  Tilt.register 'mkd',      BlueClothTemplate
 
437
  Tilt.register 'md',       BlueClothTemplate
 
438
  
 
439
  get '/' do
 
440
    markdown :index
 
441
  end
 
442
 
 
443
Renders <tt>./views/index.md</tt> with BlueCloth.
 
444
 
 
445
=== Textile Templates
 
446
 
 
447
The <tt>RedCloth</tt> gem/library is required to render Textile templates:
 
448
 
 
449
  # You'll need to require redcloth in your app
 
450
  require "redcloth"
 
451
 
 
452
  get '/' do
 
453
    textile :index
 
454
  end
 
455
 
 
456
Renders <tt>./views/index.textile</tt>.
 
457
 
 
458
It is not possible to call methods from textile, nor to pass locals to it. You
 
459
therefore will usually use it in combination with another rendering engine:
 
460
 
 
461
  erb :overview, :locals => { :text => textile(:introduction) }
 
462
 
 
463
Note that you may also call the +textile+ method from within other templates:
 
464
 
 
465
  %h1 Hello From Haml!
 
466
  %p= textile(:greetings)
 
467
 
 
468
Since you cannot call Ruby from Textile, you cannot use layouts written in
 
469
Textile. However, it is possible to use another rendering engine for the
 
470
template than for the layout by passing the <tt>:layout_engine</tt> option:
 
471
 
 
472
  get '/' do
 
473
    textile :index, :layout_engine => :erb
 
474
  end
 
475
 
 
476
This will render <tt>./views/index.textile</tt> with
 
477
<tt>./views/layout.erb</tt> as layout.
 
478
 
 
479
Remember that you can set such rendering options globally:
 
480
 
 
481
  set :textile, :layout_engine => :haml, :layout => :post
 
482
 
 
483
  get '/' do
 
484
    textile :index
 
485
  end
 
486
 
 
487
This will render <tt>./views/index.textile</tt> (and any other Textile
 
488
template) with <tt>./views/post.haml</tt> as layout.
 
489
 
 
490
=== RDoc Templates
 
491
 
 
492
The <tt>rdoc</tt> gem/library is required to render RDoc templates:
 
493
 
 
494
  # You'll need to require rdoc/markup/to_html in your app
 
495
  require "rdoc/markup/to_html"
 
496
 
 
497
  get '/' do
 
498
    rdoc :index
 
499
  end
 
500
 
 
501
Renders <tt>./views/index.rdoc</tt>.
 
502
 
 
503
It is not possible to call methods from rdoc, nor to pass locals to it. You
 
504
therefore will usually use it in combination with another rendering engine:
 
505
 
 
506
  erb :overview, :locals => { :text => rdoc(:introduction) }
 
507
 
 
508
Note that you may also call the +rdoc+ method from within other templates:
 
509
 
 
510
  %h1 Hello From Haml!
 
511
  %p= rdoc(:greetings)
 
512
 
 
513
Since you cannot call Ruby from RDoc, you cannot use layouts written in
 
514
RDoc. However, it is possible to use another rendering engine for the
 
515
template than for the layout by passing the <tt>:layout_engine</tt> option:
 
516
 
 
517
  get '/' do
 
518
    rdoc :index, :layout_engine => :erb
 
519
  end
 
520
 
 
521
This will render <tt>./views/index.rdoc</tt> with <tt>./views/layout.erb</tt> as
 
522
layout.
 
523
 
 
524
Remember that you can set such rendering options globally:
 
525
 
 
526
  set :rdoc, :layout_engine => :haml, :layout => :post
 
527
 
 
528
  get '/' do
 
529
    rdoc :index
 
530
  end
 
531
 
 
532
This will render <tt>./views/index.rdoc</tt> (and any other RDoc template)
 
533
with <tt>./views/post.haml</tt> as layout.
 
534
 
 
535
=== Radius Templates
 
536
 
 
537
The <tt>radius</tt> gem/library is required to render Radius templates:
 
538
 
 
539
  # You'll need to require radius in your app
 
540
  require 'radius'
 
541
 
 
542
  get '/' do
 
543
    radius :index
 
544
  end
 
545
 
 
546
Renders <tt>./views/index.radius</tt>.
 
547
 
 
548
Since you cannot call Ruby methods (except for +yield+) from a Radius
 
549
template, you almost always want to pass locals to it:
 
550
 
 
551
  radius :index, :locals => { :key => 'value' }
 
552
 
 
553
=== Markaby Templates
 
554
 
 
555
The <tt>markaby</tt> gem/library is required to render Markaby templates:
 
556
 
 
557
  # You'll need to require markaby in your app
 
558
  require 'markaby'
 
559
 
 
560
  get '/' do
 
561
    markaby :index
 
562
  end
 
563
 
 
564
Renders <tt>./views/index.mab</tt>.
 
565
 
 
566
You may also use inline Markaby:
 
567
 
 
568
  get '/' do
 
569
    markaby { h1 "Welcome!" }
 
570
  end
 
571
 
 
572
=== Slim Templates
 
573
 
 
574
The <tt>slim</tt> gem/library is required to render Slim templates:
 
575
 
 
576
  # You'll need to require slim in your app
 
577
  require 'slim'
 
578
 
 
579
  get '/' do
 
580
    slim :index
 
581
  end
 
582
 
 
583
Renders <tt>./views/index.slim</tt>.
 
584
 
 
585
=== CoffeeScript Templates
 
586
 
 
587
The <tt>coffee-script</tt> gem/library and at least <b>one</b> of the
 
588
following options to execute JavaScript:
 
589
 
 
590
* +node+ (from Node.js) in your path
 
591
* you must be running on OSX
 
592
* +therubyracer+ gem/library
 
593
 
 
594
See http://github.com/josh/ruby-coffee-script for an updated list of options.
 
595
 
 
596
Now you can render CoffeeScript templates:
 
597
 
 
598
  # You'll need to require coffee-script in your app
 
599
  require 'coffee-script'
 
600
 
 
601
  get '/application.js' do
 
602
    coffee :application
 
603
  end
 
604
 
 
605
Renders <tt>./views/application.coffee</tt>.
 
606
 
 
607
=== Embedded Templates
 
608
 
 
609
  get '/' do
 
610
    haml '%div.title Hello World'
 
611
  end
 
612
 
 
613
Renders the embedded template string.
 
614
 
 
615
=== Accessing Variables in Templates
 
616
 
 
617
Templates are evaluated within the same context as route handlers. Instance
 
618
variables set in route handlers are directly accessible by templates:
 
619
 
 
620
  get '/:id' do
 
621
    @foo = Foo.find(params[:id])
 
622
    haml '%h1= @foo.name'
 
623
  end
 
624
 
 
625
Or, specify an explicit Hash of local variables:
 
626
 
 
627
  get '/:id' do
 
628
    foo = Foo.find(params[:id])
 
629
    haml '%h1= foo.name', :locals => { :foo => foo }
 
630
  end
 
631
 
 
632
This is typically used when rendering templates as partials from within
 
633
other templates.
 
634
 
 
635
=== Inline Templates
 
636
 
 
637
Templates may be defined at the end of the source file:
 
638
 
 
639
  require 'sinatra'
 
640
 
 
641
  get '/' do
 
642
    haml :index
 
643
  end
 
644
 
 
645
  __END__
 
646
 
 
647
  @@ layout
 
648
  %html
 
649
    = yield
 
650
 
 
651
  @@ index
 
652
  %div.title Hello world!!!!!
 
653
 
 
654
NOTE: Inline templates defined in the source file that requires sinatra are
 
655
automatically loaded. Call <tt>enable :inline_templates</tt> explicitly if you
 
656
have inline templates in other source files.
 
657
 
 
658
=== Named Templates
 
659
 
 
660
Templates may also be defined using the top-level <tt>template</tt> method:
 
661
 
 
662
  template :layout do
 
663
    "%html\n  =yield\n"
 
664
  end
 
665
 
 
666
  template :index do
 
667
    '%div.title Hello World!'
 
668
  end
 
669
 
 
670
  get '/' do
 
671
    haml :index
 
672
  end
 
673
 
 
674
If a template named "layout" exists, it will be used each time a template
 
675
is rendered. You can individually disable layouts by passing <tt>:layout => false</tt>
 
676
or disable them by default via <tt>set :haml, :layout => false</tt>:
 
677
 
 
678
  get '/' do
 
679
    haml :index, :layout => !request.xhr?
 
680
  end
 
681
 
 
682
=== Associating File Extensions
 
683
 
 
684
To associate a file extension with a template engine, use
 
685
<tt>Tilt.register</tt>. For instance, if you like to use the file extension
 
686
+tt+ for Textile templates, you can do the following:
 
687
 
 
688
  Tilt.register :tt, Tilt[:textile]
 
689
 
 
690
=== Adding Your Own Template Engine
 
691
 
 
692
First, register your engine with Tilt, then create a rendering method:
 
693
 
 
694
  Tilt.register :myat, MyAwesomeTemplateEngine
 
695
 
 
696
  helpers do
 
697
    def myat(*args) render(:myat, *args) end
 
698
  end
 
699
 
 
700
  get '/' do
 
701
    myat :index
 
702
  end
 
703
 
 
704
Renders <tt>./views/index.myat</tt>. See https://github.com/rtomayko/tilt to
 
705
learn more about Tilt.
 
706
 
 
707
== Filters
 
708
 
 
709
Before filters are evaluated before each request within the same
 
710
context as the routes will be and can modify the request and response. Instance
 
711
variables set in filters are accessible by routes and templates:
 
712
 
 
713
  before do
 
714
    @note = 'Hi!'
 
715
    request.path_info = '/foo/bar/baz'
 
716
  end
 
717
 
 
718
  get '/foo/*' do
 
719
    @note #=> 'Hi!'
 
720
    params[:splat] #=> 'bar/baz'
 
721
  end
 
722
 
 
723
After filters are evaluated after each request within the same context and can
 
724
also modify the request and response. Instance variables set in before filters
 
725
and routes are accessible by after filters:
 
726
 
 
727
  after do
 
728
    puts response.status
 
729
  end
 
730
 
 
731
Note: Unless you use the +body+ method rather than just returning a String from
 
732
the routes, the body will not yet be available in the after filter, since it is
 
733
generated later on.
 
734
 
 
735
Filters optionally take a pattern, causing them to be evaluated only if the
 
736
request path matches that pattern:
 
737
 
 
738
  before '/protected/*' do
 
739
    authenticate!
 
740
  end
 
741
 
 
742
  after '/create/:slug' do |slug|
 
743
    session[:last_slug] = slug
 
744
  end
 
745
 
 
746
Like routes, filters also take conditions:
 
747
 
 
748
  before :agent => /Songbird/ do
 
749
    # ...
 
750
  end
 
751
  
 
752
  after '/blog/*', :host_name => 'example.com' do
 
753
    # ...
 
754
  end
 
755
 
 
756
== Helpers
 
757
 
 
758
Use the top-level <tt>helpers</tt> method to define helper methods for use in
 
759
route handlers and templates:
 
760
 
 
761
  helpers do
 
762
    def bar(name)
 
763
      "#{name}bar"
 
764
    end
 
765
  end
 
766
 
 
767
  get '/:name' do
 
768
    bar(params[:name])
 
769
  end
 
770
 
 
771
=== Using Sessions
 
772
 
 
773
A session is used to keep state during requests. If activated, you have one
 
774
session hash per user session:
 
775
 
 
776
  enable :sessions
 
777
 
 
778
  get '/' do
 
779
    "value = " << session[:value].inspect
 
780
  end
 
781
 
 
782
  get '/:value' do
 
783
    session[:value] = params[:value]
 
784
  end
 
785
 
 
786
Note that <tt>enable :sessions</tt> actually stores all data in a cookie. This
 
787
might not always be what you want (storing lots of data will increase your
 
788
traffic, for instance). You can use any Rack session middleware, in order to
 
789
do so, do *not* call <tt>enable :sessions</tt>, but instead pull in your
 
790
middleware of choice how you would any other middleware:
 
791
 
 
792
  use Rack::Session::Pool, :expire_after => 2592000
 
793
 
 
794
  get '/' do
 
795
    "value = " << session[:value].inspect
 
796
  end
 
797
 
 
798
  get '/:value' do
 
799
    session[:value] = params[:value]
 
800
  end
 
801
 
 
802
To improve security, the session data in the cookie is signed with a session
 
803
secret. A random secret is generate for you by Sinatra. However, since this
 
804
secret will change with every start of your application, you might want to
 
805
set the secret yourself, so all your application instances share it:
 
806
 
 
807
  set :session_secret, 'super secret'
 
808
 
 
809
=== Halting
 
810
 
 
811
To immediately stop a request within a filter or route use:
 
812
 
 
813
  halt
 
814
 
 
815
You can also specify the status when halting:
 
816
 
 
817
  halt 410
 
818
 
 
819
Or the body:
 
820
 
 
821
  halt 'this will be the body'
 
822
 
 
823
Or both:
 
824
 
 
825
  halt 401, 'go away!'
 
826
 
 
827
With headers:
 
828
 
 
829
  halt 402, {'Content-Type' => 'text/plain'}, 'revenge'
 
830
 
 
831
It is of course possible to combine a template with +halt+:
 
832
 
 
833
  halt erb(:error)
 
834
 
 
835
=== Passing
 
836
 
 
837
A route can punt processing to the next matching route using <tt>pass</tt>:
 
838
 
 
839
  get '/guess/:who' do
 
840
    pass unless params[:who] == 'Frank'
 
841
    'You got me!'
 
842
  end
 
843
 
 
844
  get '/guess/*' do
 
845
    'You missed!'
 
846
  end
 
847
 
 
848
The route block is immediately exited and control continues with the next
 
849
matching route. If no matching route is found, a 404 is returned.
 
850
 
 
851
=== Triggering Another Route
 
852
 
 
853
Sometimes +pass+ is not what you want, instead you would like to get the result
 
854
of calling another route. Simply use +call+ to achieve this:
 
855
 
 
856
  get '/foo' do
 
857
    status, headers, body = call request.env.merge("PATH_INFO" => '/bar')
 
858
    [status, body.upcase]
 
859
  end
 
860
 
 
861
  get '/bar' do
 
862
    "bar"
 
863
  end
 
864
 
 
865
Note that in the example above, you would ease testing and increase performance
 
866
by simply moving <tt>"bar"</tt> into a helper used by both <tt>/foo</tt>
 
867
and <tt>/bar</tt>.
 
868
 
 
869
If you want the request to be sent to the same application instance rather than
 
870
a duplicate, use <tt>call!</tt> instead of <tt>call</tt>.
 
871
 
 
872
Check out the Rack specification if you want to learn more about <tt>call</tt>.
 
873
 
 
874
=== Setting Body, Status Code and Headers
 
875
 
 
876
It is possible and recommended to set the status code and response body with the
 
877
return value of the route block. However, in some scenarios you might want to
 
878
set the body at an arbitrary point in the execution flow. You can do so with the
 
879
+body+ helper method. If you do so, you can use that method from there on to
 
880
access the body:
 
881
 
 
882
  get '/foo' do
 
883
    body "bar"
 
884
  end
 
885
  
 
886
  after do
 
887
    puts body
 
888
  end
 
889
 
 
890
It is also possible to pass a block to +body+, which will be executed by the Rack
 
891
handler (this can be used to implement streaming, see "Return Values").
 
892
 
 
893
Similar to the body, you can also set the status code and headers:
 
894
 
 
895
  get '/foo' do
 
896
    status 418
 
897
    headers \
 
898
      "Allow"   => "BREW, POST, GET, PROPFIND, WHEN"
 
899
      "Refresh" => "Refresh: 20; http://www.ietf.org/rfc/rfc2324.txt"
 
900
    body "I'm a tea pot!"
 
901
  end
 
902
 
 
903
Like +body+, +headers+ and +status+ with no arguments can be used to access
 
904
their current values.
 
905
 
 
906
=== Mime Types
 
907
 
 
908
When using <tt>send_file</tt> or static files you may have mime types Sinatra
 
909
doesn't understand. Use +mime_type+ to register them by file extension:
 
910
 
 
911
  mime_type :foo, 'text/foo'
 
912
 
 
913
You can also use it with the +content_type+ helper:
 
914
 
 
915
  get '/' do
 
916
    content_type :foo
 
917
    "foo foo foo"
 
918
  end
 
919
 
 
920
=== Generating URLs
 
921
 
 
922
For generating URLs you should use the +url+ helper method, for instance, in
 
923
Haml:
 
924
 
 
925
  %a{:href => url('/foo')} foo
 
926
 
 
927
It takes reverse proxies and Rack routers into account, if present.
 
928
 
 
929
This method is also aliased to +to+ (see below for an example).
 
930
 
 
931
=== Browser Redirect
 
932
 
 
933
You can trigger a browser redirect with the +redirect+ helper method:
 
934
 
 
935
  get '/foo' do
 
936
    redirect to('/bar')
 
937
  end
 
938
 
 
939
Any additional parameters are handled like arguments passed to +halt+:
 
940
 
 
941
  redirect to('/bar'), 303
 
942
  redirect 'http://google.com', 'wrong place, buddy'
 
943
 
 
944
You can also easily redirect back to the page the user came from with
 
945
<tt>redirect back</tt>:
 
946
 
 
947
  get '/foo' do
 
948
    "<a href='/bar'>do something</a>"
 
949
  end
 
950
 
 
951
  get '/bar' do
 
952
    do_something
 
953
    redirect back
 
954
  end
 
955
 
 
956
To pass arguments with a redirect, either add them to the query:
 
957
 
 
958
  redirect to('/bar?sum=42')
 
959
 
 
960
Or use a session:
 
961
 
 
962
  enable :session
 
963
  
 
964
  get '/foo' do
 
965
    session[:secret] = 'foo'
 
966
    redirect to('/bar')
 
967
  end
 
968
  
 
969
  get '/bar' do
 
970
    session[:secret]
 
971
  end
 
972
 
 
973
=== Cache Control
 
974
 
 
975
Setting your headers correctly is the foundation for proper HTTP caching.
 
976
 
 
977
You can easily set the Cache-Control header with like this:
 
978
 
 
979
  get '/' do
 
980
    cache_control :public
 
981
    "cache it!"
 
982
  end
 
983
 
 
984
Pro tip: Set up caching in a before filter:
 
985
 
 
986
  before do
 
987
    cache_control :public, :must_revalidate, :max_age => 60
 
988
  end
 
989
 
 
990
If you are using the +expires+ helper to set the corresponding header,
 
991
<tt>Cache-Control</tt> will be set automatically for you:
 
992
 
 
993
  before do
 
994
    expires 500, :public, :must_revalidate
 
995
  end
 
996
 
 
997
To properly use caches, you should consider using +etag+ and +last_modified+.
 
998
It is recommended to call those helpers *before* doing heavy lifting, as they
 
999
will immediately flush a response if the client already has the current
 
1000
version in its cache:
 
1001
 
 
1002
  get '/article/:id' do
 
1003
    @article = Article.find params[:id]
 
1004
    last_modified @article.updated_at
 
1005
    etag @article.sha1
 
1006
    erb :article
 
1007
  end
 
1008
 
 
1009
It is also possible to use a
 
1010
{weak ETag}[http://en.wikipedia.org/wiki/HTTP_ETag#Strong_and_weak_validation]:
 
1011
 
 
1012
  etag @article.sha1, :weak
 
1013
 
 
1014
These helpers will not do any caching for you, but rather feed the necessary
 
1015
information to your cache. If you are looking for a quick caching solutions, try
 
1016
{rack-cache}[http://rtomayko.github.com/rack-cache/]:
 
1017
 
 
1018
  require "rack/cache"
 
1019
  require "sinatra"
 
1020
  
 
1021
  use Rack::Cache
 
1022
  
 
1023
  get '/' do
 
1024
    cache_control :public, :max_age => 36000
 
1025
    sleep 5
 
1026
    "hello"
 
1027
  end
 
1028
 
 
1029
=== Sending Files
 
1030
 
 
1031
For sending files, you can use the <tt>send_file</tt> helper method:
 
1032
 
 
1033
  get '/' do
 
1034
    send_file 'foo.png'
 
1035
  end
 
1036
 
 
1037
It also takes a couple of options:
 
1038
 
 
1039
  send_file 'foo.png', :type => :jpg
 
1040
 
 
1041
The options are:
 
1042
 
 
1043
[filename]
 
1044
  file name, in response, defaults to the real file name.
 
1045
 
 
1046
[last_modified]
 
1047
  value for Last-Modified header, defaults to the file's mtime.
 
1048
 
 
1049
[type]
 
1050
  content type to use, guessed from the file extension if missing.
 
1051
 
 
1052
[disposition]
 
1053
  used for Content-Disposition, possible values: +nil+ (default),
 
1054
  <tt>:attachment</tt> and <tt>:inline</tt>
 
1055
 
 
1056
[length]
 
1057
  Content-Length header, defaults to file size.
 
1058
 
 
1059
If supported by the Rack handler, other means than streaming from the Ruby
 
1060
process will be used. If you use this helper method, Sinatra will automatically
 
1061
handle range requests.
 
1062
 
 
1063
=== Accessing the Request Object
 
1064
 
 
1065
The incoming request object can be accessed from request level (filter, routes,
 
1066
error handlers) through the <tt>request</tt> method:
 
1067
 
 
1068
  # app running on http://example.com/example
 
1069
  get '/foo' do
 
1070
    request.body              # request body sent by the client (see below)
 
1071
    request.scheme            # "http"
 
1072
    request.script_name       # "/example"
 
1073
    request.path_info         # "/foo"
 
1074
    request.port              # 80
 
1075
    request.request_method    # "GET"
 
1076
    request.query_string      # ""
 
1077
    request.content_length    # length of request.body
 
1078
    request.media_type        # media type of request.body
 
1079
    request.host              # "example.com"
 
1080
    request.get?              # true (similar methods for other verbs)
 
1081
    request.form_data?        # false
 
1082
    request["SOME_HEADER"]    # value of SOME_HEADER header
 
1083
    request.referrer          # the referrer of the client or '/'
 
1084
    request.user_agent        # user agent (used by :agent condition)
 
1085
    request.cookies           # hash of browser cookies
 
1086
    request.xhr?              # is this an ajax request?
 
1087
    request.url               # "http://example.com/example/foo"
 
1088
    request.path              # "/example/foo"
 
1089
    request.ip                # client IP address
 
1090
    request.secure?           # false (would be true over ssl)
 
1091
    request.forwarded?        # true (if running behind a reverse proxy)
 
1092
    request.env               # raw env hash handed in by Rack
 
1093
  end
 
1094
 
 
1095
Some options, like <tt>script_name</tt> or <tt>path_info</tt>, can also be
 
1096
written:
 
1097
 
 
1098
  before { request.path_info = "/" }
 
1099
  
 
1100
  get "/" do
 
1101
    "all requests end up here"
 
1102
  end
 
1103
 
 
1104
The <tt>request.body</tt> is an IO or StringIO object:
 
1105
 
 
1106
  post "/api" do
 
1107
    request.body.rewind  # in case someone already read it
 
1108
    data = JSON.parse request.body.read
 
1109
    "Hello #{data['name']}!"
 
1110
  end
 
1111
 
 
1112
=== Attachments
 
1113
 
 
1114
You can use the +attachment+ helper to tell the browser the response should be
 
1115
stored on disk rather than displayed in the browser:
 
1116
 
 
1117
  get '/' do
 
1118
    attachment
 
1119
    "store it!"
 
1120
  end
 
1121
 
 
1122
You can also pass it a file name:
 
1123
 
 
1124
  get '/' do
 
1125
    attachment "info.txt"
 
1126
    "store it!"
 
1127
  end
 
1128
 
 
1129
=== Looking Up Template Files
 
1130
 
 
1131
The <tt>find_template</tt> helper is used to find template files for rendering:
 
1132
 
 
1133
  find_template settings.views, 'foo', Tilt[:haml] do |file|
 
1134
    puts "could be #{file}"
 
1135
  end
 
1136
 
 
1137
This is not really useful. But it is useful that you can actually override this
 
1138
method to hook in your own lookup mechanism. For instance, if you want to be
 
1139
able to use more than one view directory:
 
1140
 
 
1141
  set :views, ['views', 'templates']
 
1142
 
 
1143
  helpers do
 
1144
    def find_template(views, name, engine, &block)
 
1145
      Array(views).each { |v| super(v, name, engine, &block) }
 
1146
    end
 
1147
  end
 
1148
 
 
1149
Another example would be using different directories for different engines:
 
1150
 
 
1151
  set :views, :sass => 'views/sass', :haml => 'templates', :default => 'views'
 
1152
 
 
1153
  helpers do
 
1154
    def find_template(views, name, engine, &block)
 
1155
      _, folder = views.detect { |k,v| engine == Tilt[k] }
 
1156
      folder ||= views[:default]
 
1157
      super(folder, name, engine, &block)
 
1158
    end
 
1159
  end
 
1160
 
 
1161
You can also easily wrap this up in an extension and share with others!
 
1162
 
 
1163
Note that <tt>find_template</tt> does not check if the file really exists but
 
1164
rather calls the given block for all possible paths. This is not a performance
 
1165
issue, since +render+ will use +break+ as soon as a file is found. Also,
 
1166
template locations (and content) will be cached if you are not running in
 
1167
development mode. You should keep that in mind if you write a really crazy
 
1168
method.
 
1169
 
 
1170
== Configuration
 
1171
 
 
1172
Run once, at startup, in any environment:
 
1173
 
 
1174
  configure do
 
1175
    # setting one option
 
1176
    set :option, 'value'
 
1177
    
 
1178
    # setting multiple options
 
1179
    set :a => 1, :b => 2
 
1180
    
 
1181
    # same as `set :option, true`
 
1182
    enable :option
 
1183
    
 
1184
    # same as `set :option, false`
 
1185
    disable :option
 
1186
    
 
1187
    # you can also have dynamic settings with blocks
 
1188
    set(:css_dir) { File.join(views, 'css') }
 
1189
  end
 
1190
 
 
1191
Run only when the environment (RACK_ENV environment variable) is set to
 
1192
<tt>:production</tt>:
 
1193
 
 
1194
  configure :production do
 
1195
    ...
 
1196
  end
 
1197
 
 
1198
Run when the environment is set to either <tt>:production</tt> or
 
1199
<tt>:test</tt>:
 
1200
 
 
1201
  configure :production, :test do
 
1202
    ...
 
1203
  end
 
1204
 
 
1205
You can access those options via <tt>settings</tt>:
 
1206
 
 
1207
  configure do
 
1208
    set :foo, 'bar'
 
1209
  end
 
1210
 
 
1211
  get '/' do
 
1212
    settings.foo? # => true
 
1213
    settings.foo  # => 'bar'
 
1214
    ...
 
1215
  end
 
1216
 
 
1217
=== Available Settings
 
1218
 
 
1219
[absolute_redirects]  If disabled, Sinatra will allow relative redirects,
 
1220
                      however, Sinatra will no longer conform with RFC 2616
 
1221
                      (HTTP 1.1), which only allows absolute redirects.
 
1222
                      
 
1223
                      Enable if your app is running behind a reverse proxy that
 
1224
                      has not been set up properly. Note that the +url+ helper
 
1225
                      will still produce absolute URLs, unless you pass in
 
1226
                      +false+ as second parameter.
 
1227
                      
 
1228
                      Disabled per default.
 
1229
 
 
1230
[add_charsets]        mime types the <tt>content_type</tt> helper will
 
1231
                      automatically add the charset info to.
 
1232
                      
 
1233
                      You should add to it rather than overriding this option:
 
1234
                      
 
1235
                        settings.add_charsets << "application/foobar"
 
1236
 
 
1237
[app_file]            main application file, used to detect project root,
 
1238
                      views and public folder and inline templates.
 
1239
 
 
1240
[bind]                IP address to bind to (default: 0.0.0.0).
 
1241
                      Only used for built-in server.
 
1242
 
 
1243
[default_encoding]    encoding to assume if unknown
 
1244
                      (defaults to <tt>"utf-8"</tt>).
 
1245
 
 
1246
[dump_errors]         display errors in the log.
 
1247
 
 
1248
[environment]         current environment, defaults to <tt>ENV['RACK_ENV']</tt>,
 
1249
                      or <tt>"development"</tt> if not available.
 
1250
 
 
1251
[logging]             use the logger.
 
1252
 
 
1253
[lock]                Places a lock around every request, only running
 
1254
                      processing on request per Ruby process concurrently.
 
1255
                      
 
1256
                      Enabled if your app is not thread-safe.
 
1257
                      Disabled per default.
 
1258
 
 
1259
[method_override]     use <tt>_method</tt> magic to allow put/delete forms in
 
1260
                      browsers that don't support it.
 
1261
 
 
1262
[port]                Port to listen on. Only used for built-in server.
 
1263
 
 
1264
[prefixed_redirects]  Whether or not to insert <tt>request.script_name</tt> into
 
1265
                      redirects if no absolute path is given. That way
 
1266
                      <tt>redirect '/foo'</tt> would behave like
 
1267
                      <tt>redirect to('/foo')</tt>. Disabled per default.
 
1268
 
 
1269
[public]              folder public files are served from
 
1270
 
 
1271
[reload_templates]    whether or not to reload templates between requests.
 
1272
                      Enabled in development mode and on Ruby 1.8.6 (to
 
1273
                      compensate a bug in Ruby causing a memory leak).
 
1274
 
 
1275
[root]                project root folder.
 
1276
 
 
1277
[raise_errors]        raise exceptions (will stop application).
 
1278
 
 
1279
[run]                 if enabled, Sinatra will handle starting the web server,
 
1280
                      do not enable if using rackup or other means.
 
1281
 
 
1282
[running]             is the built-in server running now?
 
1283
                      do not change this setting!
 
1284
 
 
1285
[server]              server or list of servers to use for built-in server.
 
1286
                      defaults to ['thin', 'mongrel', 'webrick'], order indicates
 
1287
                      priority.
 
1288
 
 
1289
[sessions]            enable cookie based sessions.
 
1290
 
 
1291
[show_exceptions]     show a stack trace in the browser.
 
1292
 
 
1293
[static]              Whether Sinatra should handle serving static files.
 
1294
                      Disable when using a Server able to do this on its own.
 
1295
                      Disabling will boost performance.
 
1296
                      Enabled per default.
 
1297
 
 
1298
[views]               views folder.
 
1299
 
 
1300
== Error Handling
 
1301
 
 
1302
Error handlers run within the same context as routes and before filters, which
 
1303
means you get all the goodies it has to offer, like <tt>haml</tt>,
 
1304
<tt>erb</tt>, <tt>halt</tt>, etc.
 
1305
 
 
1306
=== Not Found
 
1307
 
 
1308
When a <tt>Sinatra::NotFound</tt> exception is raised, or the response's status
 
1309
code is 404, the <tt>not_found</tt> handler is invoked:
 
1310
 
 
1311
  not_found do
 
1312
    'This is nowhere to be found.'
 
1313
  end
 
1314
 
 
1315
=== Error
 
1316
 
 
1317
The +error+ handler is invoked any time an exception is raised from a route
 
1318
block or a filter. The exception object can be obtained from the
 
1319
<tt>sinatra.error</tt> Rack variable:
 
1320
 
 
1321
  error do
 
1322
    'Sorry there was a nasty error - ' + env['sinatra.error'].name
 
1323
  end
 
1324
 
 
1325
Custom errors:
 
1326
 
 
1327
  error MyCustomError do
 
1328
    'So what happened was...' + request.env['sinatra.error'].message
 
1329
  end
 
1330
 
 
1331
Then, if this happens:
 
1332
 
 
1333
  get '/' do
 
1334
    raise MyCustomError, 'something bad'
 
1335
  end
 
1336
 
 
1337
You get this:
 
1338
 
 
1339
  So what happened was... something bad
 
1340
 
 
1341
Alternatively, you can install an error handler for a status code:
 
1342
 
 
1343
  error 403 do
 
1344
    'Access forbidden'
 
1345
  end
 
1346
 
 
1347
  get '/secret' do
 
1348
    403
 
1349
  end
 
1350
 
 
1351
Or a range:
 
1352
 
 
1353
  error 400..510 do
 
1354
    'Boom'
 
1355
  end
 
1356
 
 
1357
Sinatra installs special <tt>not_found</tt> and <tt>error</tt> handlers when
 
1358
running under the development environment.
 
1359
 
 
1360
== Rack Middleware
 
1361
 
 
1362
Sinatra rides on Rack[http://rack.rubyforge.org/], a minimal standard
 
1363
interface for Ruby web frameworks. One of Rack's most interesting capabilities
 
1364
for application developers is support for "middleware" -- components that sit
 
1365
between the server and your application monitoring and/or manipulating the
 
1366
HTTP request/response to provide various types of common functionality.
 
1367
 
 
1368
Sinatra makes building Rack middleware pipelines a cinch via a top-level
 
1369
+use+ method:
 
1370
 
 
1371
  require 'sinatra'
 
1372
  require 'my_custom_middleware'
 
1373
 
 
1374
  use Rack::Lint
 
1375
  use MyCustomMiddleware
 
1376
 
 
1377
  get '/hello' do
 
1378
    'Hello World'
 
1379
  end
 
1380
 
 
1381
The semantics of +use+ are identical to those defined for the
 
1382
Rack::Builder[http://rack.rubyforge.org/doc/classes/Rack/Builder.html] DSL
 
1383
(most frequently used from rackup files). For example, the +use+ method
 
1384
accepts multiple/variable args as well as blocks:
 
1385
 
 
1386
  use Rack::Auth::Basic do |username, password|
 
1387
    username == 'admin' && password == 'secret'
 
1388
  end
 
1389
 
 
1390
Rack is distributed with a variety of standard middleware for logging,
 
1391
debugging, URL routing, authentication, and session handling. Sinatra uses
 
1392
many of these components automatically based on configuration so you
 
1393
typically don't have to +use+ them explicitly.
 
1394
 
 
1395
== Testing
 
1396
 
 
1397
Sinatra tests can be written using any Rack-based testing library
 
1398
or framework. {Rack::Test}[http://gitrdoc.com/brynary/rack-test] is
 
1399
recommended:
 
1400
 
 
1401
  require 'my_sinatra_app'
 
1402
  require 'test/unit'
 
1403
  require 'rack/test'
 
1404
 
 
1405
  class MyAppTest < Test::Unit::TestCase
 
1406
    include Rack::Test::Methods
 
1407
 
 
1408
    def app
 
1409
      Sinatra::Application
 
1410
    end
 
1411
 
 
1412
    def test_my_default
 
1413
      get '/'
 
1414
      assert_equal 'Hello World!', last_response.body
 
1415
    end
 
1416
 
 
1417
    def test_with_params
 
1418
      get '/meet', :name => 'Frank'
 
1419
      assert_equal 'Hello Frank!', last_response.body
 
1420
    end
 
1421
 
 
1422
    def test_with_rack_env
 
1423
      get '/', {}, 'HTTP_USER_AGENT' => 'Songbird'
 
1424
      assert_equal "You're using Songbird!", last_response.body
 
1425
    end
 
1426
  end
 
1427
 
 
1428
NOTE: The built-in Sinatra::Test module and Sinatra::TestHarness class
 
1429
are deprecated as of the 0.9.2 release.
 
1430
 
 
1431
== Sinatra::Base - Middleware, Libraries, and Modular Apps
 
1432
 
 
1433
Defining your app at the top-level works well for micro-apps but has
 
1434
considerable drawbacks when building reusable components such as Rack
 
1435
middleware, Rails metal, simple libraries with a server component, or
 
1436
even Sinatra extensions. The top-level DSL pollutes the Object namespace
 
1437
and assumes a micro-app style configuration (e.g., a single application
 
1438
file, ./public and ./views directories, logging, exception detail page,
 
1439
etc.). That's where Sinatra::Base comes into play:
 
1440
 
 
1441
  require 'sinatra/base'
 
1442
 
 
1443
  class MyApp < Sinatra::Base
 
1444
    set :sessions, true
 
1445
    set :foo, 'bar'
 
1446
 
 
1447
    get '/' do
 
1448
      'Hello world!'
 
1449
    end
 
1450
  end
 
1451
 
 
1452
The methods available to Sinatra::Base subclasses are exactly as those
 
1453
available via the top-level DSL. Most top-level apps can be converted to
 
1454
Sinatra::Base components with two modifications:
 
1455
 
 
1456
* Your file should require <tt>sinatra/base</tt> instead of +sinatra+;
 
1457
  otherwise, all of Sinatra's DSL methods are imported into the main
 
1458
  namespace.
 
1459
* Put your app's routes, error handlers, filters, and options in a subclass
 
1460
  of Sinatra::Base.
 
1461
 
 
1462
<tt>Sinatra::Base</tt> is a blank slate. Most options are disabled by default,
 
1463
including the built-in server. See {Options and Configuration}[http://sinatra.github.com/configuration.html]
 
1464
for details on available options and their behavior.
 
1465
 
 
1466
=== Modular vs. Classic Style
 
1467
 
 
1468
Contrary to common belief, there is nothing wrong with classic style. If it
 
1469
suits your application, you do not have to switch to a modular application.
 
1470
 
 
1471
There are only two downsides compared with modular style:
 
1472
 
 
1473
* You may only have one Sinatra application per Ruby process. If you plan to
 
1474
  use more, switch to modular style.
 
1475
 
 
1476
* Classic style pollutes Object with delegator methods. If you plan to ship
 
1477
  your application in a library/gem, switch to modular style.
 
1478
 
 
1479
There is no reason you cannot mix modular and classic style.
 
1480
 
 
1481
If switching from one style to the other, you should be aware of slight
 
1482
differences in the setting:
 
1483
 
 
1484
  Setting             Classic                 Modular
 
1485
 
 
1486
  app_file            file loading sinatra    nil
 
1487
  run                 $0 == app_file          false
 
1488
  logging             true                    false
 
1489
  method_override     true                    false
 
1490
  inline_templates    true                    false
 
1491
 
 
1492
 
 
1493
=== Serving a Modular Application
 
1494
 
 
1495
There are two common options for starting a modular app, actively starting with
 
1496
<tt>run!</tt>:
 
1497
 
 
1498
  # my_app.rb
 
1499
  require 'sinatra/base'
 
1500
  
 
1501
  class MyApp < Sinatra::Base
 
1502
    # ... app code here ...
 
1503
    
 
1504
    # start the server if ruby file executed directly
 
1505
    run! if app_file == $0
 
1506
  end
 
1507
 
 
1508
Start with:
 
1509
 
 
1510
  ruby my_app.rb
 
1511
 
 
1512
Or with a <tt>config.ru</tt>, which allows using any Rack handler:
 
1513
 
 
1514
  # config.ru
 
1515
  require 'my_app'
 
1516
  run MyApp
 
1517
 
 
1518
Run:
 
1519
 
 
1520
  rackup -p 4567
 
1521
 
 
1522
=== Using a Classic Style Application with a config.ru
 
1523
 
 
1524
Write your app file:
 
1525
 
 
1526
  # app.rb
 
1527
  require 'sinatra'
 
1528
  
 
1529
  get '/' do
 
1530
    'Hello world!'
 
1531
  end
 
1532
 
 
1533
And a corresponding <tt>config.ru</tt>:
 
1534
 
 
1535
  require 'app'
 
1536
  run Sinatra::Application
 
1537
 
 
1538
=== When to use a config.ru?
 
1539
 
 
1540
Good signs you probably want to use a <tt>config.ru</tt>:
 
1541
 
 
1542
* You want to deploy with a different Rack handler (Passenger, Unicorn,
 
1543
  Heroku, ...).
 
1544
* You want to use more than one subclass of <tt>Sinatra::Base</tt>.
 
1545
* You want to use Sinatra only for middleware, but not as endpoint.
 
1546
 
 
1547
<b>There is no need to switch to a <tt>config.ru</tt> only because you
 
1548
switched to modular style, and you don't have to use modular style for running
 
1549
with a <tt>config.ru</tt>.</b>
 
1550
 
 
1551
=== Using Sinatra as Middleware
 
1552
 
 
1553
Not only is Sinatra able to use other Rack middleware, any Sinatra application
 
1554
can in turn be added in front of any Rack endpoint as middleware itself. This
 
1555
endpoint could be another Sinatra application, or any other Rack-based
 
1556
application (Rails/Ramaze/Camping/...):
 
1557
 
 
1558
  require 'sinatra/base'
 
1559
  
 
1560
  class LoginScreen < Sinatra::Base
 
1561
    enable :sessions
 
1562
    
 
1563
    get('/login') { haml :login }
 
1564
    
 
1565
    post('/login') do
 
1566
      if params[:name] = 'admin' and params[:password] = 'admin'
 
1567
        session['user_name'] = params[:name]
 
1568
      else
 
1569
        redirect '/login'
 
1570
      end
 
1571
    end
 
1572
  end
 
1573
  
 
1574
  class MyApp < Sinatra::Base
 
1575
    # middleware will run before filters
 
1576
    use LoginScreen
 
1577
    
 
1578
    before do
 
1579
      unless session['user_name']
 
1580
        halt "Access denied, please <a href='/login'>login</a>."
 
1581
      end
 
1582
    end
 
1583
    
 
1584
    get('/') { "Hello #{session['user_name']}." }
 
1585
  end
 
1586
 
 
1587
=== Dynamic Application Creation
 
1588
 
 
1589
Sometimes you want to create new applications at runtime without having to
 
1590
assign them to a constant, you can do this with `Sinatra.new`:
 
1591
 
 
1592
  require 'sinatra/base'
 
1593
  my_app = Sinatra.new { get('/') { "hi" } }
 
1594
  my_app.run!
 
1595
 
 
1596
It takes the application to inherit from as optional argument:
 
1597
 
 
1598
  require 'sinatra/base'
 
1599
 
 
1600
  controller = Sinatra.new do
 
1601
    enable :logging
 
1602
    helpers MyHelpers
 
1603
  end
 
1604
 
 
1605
  map('/a') do
 
1606
    run Sinatra.new(controller) { get('/') { 'a' } }
 
1607
  end
 
1608
 
 
1609
  map('/b') do
 
1610
    run Sinatra.new(controller) { get('/') { 'b' } }
 
1611
  end
 
1612
 
 
1613
This is especially useful for testing Sinatra extensions or using Sinatra in
 
1614
your own library.
 
1615
 
 
1616
This also makes using Sinatra as middleware extremely easy:
 
1617
 
 
1618
  require 'sinatra/base'
 
1619
 
 
1620
  use Sinatra do
 
1621
    get('/') { ... }
 
1622
  end
 
1623
 
 
1624
  run RailsProject::Application
 
1625
 
 
1626
== Scopes and Binding
 
1627
 
 
1628
The scope you are currently in determines what methods and variables are
 
1629
available.
 
1630
 
 
1631
=== Application/Class Scope
 
1632
 
 
1633
Every Sinatra application corresponds to a subclass of Sinatra::Base. If you
 
1634
are using the top-level DSL (<tt>require 'sinatra'</tt>), then this class is
 
1635
Sinatra::Application, otherwise it is the subclass you created explicitly. At
 
1636
class level you have methods like +get+ or +before+, but you cannot access the
 
1637
+request+ object or the +session+, as there only is a single application class
 
1638
for all requests.
 
1639
 
 
1640
Options created via +set+ are methods at class level:
 
1641
 
 
1642
    class MyApp < Sinatra::Base
 
1643
      # Hey, I'm in the application scope!
 
1644
      set :foo, 42
 
1645
      foo # => 42
 
1646
      
 
1647
      get '/foo' do
 
1648
        # Hey, I'm no longer in the application scope!
 
1649
      end
 
1650
    end
 
1651
 
 
1652
You have the application scope binding inside:
 
1653
 
 
1654
* Your application class body
 
1655
* Methods defined by extensions
 
1656
* The block passed to +helpers+
 
1657
* Procs/blocks used as value for +set+
 
1658
* The block passed to <tt>Sinatra.new</tt>
 
1659
 
 
1660
You can reach the scope object (the class) like this:
 
1661
 
 
1662
* Via the object passed to configure blocks (<tt>configure { |c| ... }</tt>)
 
1663
* +settings+ from within request scope
 
1664
 
 
1665
=== Request/Instance Scope
 
1666
 
 
1667
For every incoming request, a new instance of your application class is
 
1668
created and all handler blocks run in that scope. From within this scope you
 
1669
can access the +request+ and +session+ object or call rendering methods like
 
1670
+erb+ or +haml+. You can access the application scope from within the request
 
1671
scope via the +settings+ helper:
 
1672
 
 
1673
  class MyApp < Sinatra::Base
 
1674
    # Hey, I'm in the application scope!
 
1675
    get '/define_route/:name' do
 
1676
      # Request scope for '/define_route/:name'
 
1677
      @value = 42
 
1678
      
 
1679
      settings.get("/#{params[:name]}") do
 
1680
        # Request scope for "/#{params[:name]}"
 
1681
        @value # => nil (not the same request)
 
1682
      end
 
1683
      
 
1684
      "Route defined!"
 
1685
    end
 
1686
  end
 
1687
 
 
1688
You have the request scope binding inside:
 
1689
 
 
1690
* get/head/post/put/delete/options blocks
 
1691
* before/after filters
 
1692
* helper methods
 
1693
* templates/views
 
1694
 
 
1695
=== Delegation Scope
 
1696
 
 
1697
The delegation scope just forwards methods to the class scope. However, it
 
1698
does not behave 100% like the class scope, as you do not have the class
 
1699
binding. Only methods explicitly marked for delegation are available and you
 
1700
do not share variables/state with the class scope (read: you have a different
 
1701
+self+). You can explicitly add method delegations by calling
 
1702
<tt>Sinatra::Delegator.delegate :method_name</tt>.
 
1703
 
 
1704
You have the delegate scope binding inside:
 
1705
 
 
1706
* The top level binding, if you did <tt>require "sinatra"</tt>
 
1707
* An object extended with the <tt>Sinatra::Delegator</tt> mixin
 
1708
 
 
1709
Have a look at the code for yourself: here's the
 
1710
{Sinatra::Delegator mixin}[http://github.com/sinatra/sinatra/blob/ceac46f0bc129a6e994a06100aa854f606fe5992/lib/sinatra/base.rb#L1128]
 
1711
being {included into the main namespace}[http://github.com/sinatra/sinatra/blob/ceac46f0bc129a6e994a06100aa854f606fe5992/lib/sinatra/main.rb#L28].
 
1712
 
 
1713
== Command Line
 
1714
 
 
1715
Sinatra applications can be run directly:
 
1716
 
 
1717
  ruby myapp.rb [-h] [-x] [-e ENVIRONMENT] [-p PORT] [-o HOST] [-s HANDLER]
 
1718
 
 
1719
Options are:
 
1720
 
 
1721
  -h # help
 
1722
  -p # set the port (default is 4567)
 
1723
  -o # set the host (default is 0.0.0.0)
 
1724
  -e # set the environment (default is development)
 
1725
  -s # specify rack server/handler (default is thin)
 
1726
  -x # turn on the mutex lock (default is off)
 
1727
 
 
1728
== Requirements
 
1729
 
 
1730
It is recommended to install Sinatra on Ruby 1.8.7, 1.9.2, JRuby or Rubinius.
 
1731
 
 
1732
The following Ruby versions are officially supported:
 
1733
 
 
1734
[ Ruby 1.8.6 ]
 
1735
  It is not recommended to use 1.8.6 for Sinatra. However, it will be
 
1736
  officially supported until Sinatra 1.3.0 is released. RDoc and CoffeeScript
 
1737
  templates are not supported by this Ruby version. 1.8.6 includes a major
 
1738
  memory leak in its Hash implementation, which is triggered by Sinatra
 
1739
  versions prior to 1.1.1. The current version explicitly prevents this leak
 
1740
  at the cost of performance. You will have to downgrade Rack to 1.1.x, as
 
1741
  Rack >= 1.2 no longer supports 1.8.6.
 
1742
 
 
1743
[ Ruby 1.8.7 ]
 
1744
  1.8.7 is fully supported, however, if nothing is keeping you from it, we
 
1745
  recommend upgrading to 1.9.2 or switching to JRuby or Rubinius.
 
1746
 
 
1747
[ Ruby 1.9.2 ]
 
1748
  1.9.2 is supported and recommended. Note that Radius and Markaby are
 
1749
  currently not 1.9 compatible. Do not use 1.9.2p0, it is known to cause
 
1750
  segmentation faults when using Sinatra.
 
1751
 
 
1752
[ Rubinius ]
 
1753
  Rubinius is officially supported (Rubinius >= 1.2.3), everything, including
 
1754
  all template languages, works.
 
1755
 
 
1756
[ JRuby ]
 
1757
  JRuby is officially supported (JRuby >= 1.6.0). No issues with third party
 
1758
  template libraries are known, however, if you choose to use JRuby, please
 
1759
  look into JRuby rack handlers, as the Thin web server is not fully supported
 
1760
  on JRuby. JRuby's support for C extensions is still experimental, which only
 
1761
  affects RDiscount at the moment.
 
1762
 
 
1763
We also keep an eye on upcoming Ruby versions.
 
1764
 
 
1765
The following Ruby implementations are not officially supported but still are
 
1766
known to run Sinatra:
 
1767
 
 
1768
* Older versions of JRuby and Rubinius
 
1769
* MacRuby, Maglev, IronRuby
 
1770
* Ruby 1.9.0 and 1.9.1
 
1771
 
 
1772
Not being officially supported means if things only break there and not on a
 
1773
supported platform, we assume it's not our issue but theirs.
 
1774
 
 
1775
We also run our CI against ruby-head (the upcoming 1.9.3), but we can't
 
1776
guarantee anything, since it is constantly moving. Expect 1.9.3p0 to be
 
1777
supported.
 
1778
 
 
1779
Sinatra should work on any operating system supported by the chosen Ruby
 
1780
implementation.
 
1781
 
 
1782
== The Bleeding Edge
 
1783
If you would like to use Sinatra's latest bleeding code, feel free to run your
 
1784
application against the master branch, it should be rather stable.
 
1785
 
 
1786
We also push out prerelease gems from time to time, so you can do a
 
1787
 
 
1788
  gem install sinatra --pre
 
1789
 
 
1790
To get some of the latest features.
 
1791
 
 
1792
=== With Bundler
 
1793
If you want to run your application with the latest Sinatra, using
 
1794
{Bundler}[http://gembundler.com/] is the recommended way.
 
1795
 
 
1796
First, install bundler, if you haven't:
 
1797
 
 
1798
  gem install bundler
 
1799
 
 
1800
Then, in your project directory, create a +Gemfile+:
 
1801
 
 
1802
  source :rubygems
 
1803
  gem 'sinatra', :git => "git://github.com/sinatra/sinatra.git"
 
1804
  
 
1805
  # other dependencies
 
1806
  gem 'haml'                    # for instance, if you use haml
 
1807
  gem 'activerecord', '~> 3.0'  # maybe you also need ActiveRecord 3.x
 
1808
 
 
1809
Note that you will have to list all your applications dependencies in there.
 
1810
Sinatra's direct dependencies (Rack and Tilt) will, however, be automatically
 
1811
fetched and added by Bundler.
 
1812
 
 
1813
Now you can run your app like this:
 
1814
 
 
1815
  bundle exec ruby myapp.rb
 
1816
 
 
1817
=== Roll Your Own
 
1818
Create a local clone and run your app with the <tt>sinatra/lib</tt> directory
 
1819
on the <tt>$LOAD_PATH</tt>:
 
1820
 
 
1821
  cd myapp
 
1822
  git clone git://github.com/sinatra/sinatra.git
 
1823
  ruby -Isinatra/lib myapp.rb
 
1824
 
 
1825
To update the Sinatra sources in the future:
 
1826
 
 
1827
  cd myapp/sinatra
 
1828
  git pull
 
1829
 
 
1830
=== Install Globally
 
1831
 
 
1832
You can build the gem on your own:
 
1833
 
 
1834
  git clone git://github.com/sinatra/sinatra.git
 
1835
  cd sinatra
 
1836
  rake sinatra.gemspec
 
1837
  rake install
 
1838
 
 
1839
If you install gems as root, the last step should be
 
1840
 
 
1841
  sudo rake install
 
1842
 
 
1843
== Versioning
 
1844
 
 
1845
Sinatra follows {Semantic Versioning}[http://semver.org/], both SemVer and
 
1846
SemVerTag.
 
1847
 
 
1848
== Further Reading
 
1849
 
 
1850
* {Project Website}[http://www.sinatrarb.com/] - Additional documentation,
 
1851
  news, and links to other resources.
 
1852
* {Contributing}[http://www.sinatrarb.com/contributing] - Find a bug? Need
 
1853
  help? Have a patch?
 
1854
* {Issue tracker}[http://github.com/sinatra/sinatra/issues]
 
1855
* {Twitter}[http://twitter.com/sinatra]
 
1856
* {Mailing List}[http://groups.google.com/group/sinatrarb/topics]
 
1857
* {IRC: #sinatra}[irc://chat.freenode.net/#sinatra] on http://freenode.net
 
1858
* API documentation for the {latest release}[http://rubydoc.info/gems/sinatra]
 
1859
  or the {current HEAD}[http://rubydoc.info/github/sinatra/sinatra] on
 
1860
  http://rubydoc.info/
 
1861