sinatra 1.1.4 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.rdoc CHANGED
@@ -17,9 +17,12 @@ Install the gem and run with:
17
17
 
18
18
  View at: http://localhost:4567
19
19
 
20
+ It is recommended to also run <tt>gem install thin</tt>, which Sinatra will
21
+ pick up if available.
22
+
20
23
  == Routes
21
24
 
22
- In Sinatra, a route is an HTTP method paired with an URL matching pattern.
25
+ In Sinatra, a route is an HTTP method paired with a URL-matching pattern.
23
26
  Each route is associated with a block:
24
27
 
25
28
  get '/' do
@@ -37,6 +40,10 @@ Each route is associated with a block:
37
40
  delete '/' do
38
41
  .. annihilate something ..
39
42
  end
43
+
44
+ options '/' do
45
+ .. appease something ..
46
+ end
40
47
 
41
48
  Routes are matched in the order they are defined. The first route that
42
49
  matches the request is invoked.
@@ -123,7 +130,7 @@ You can easily define your own conditions:
123
130
 
124
131
  The return value of a route block determines at least the response body passed
125
132
  on to the HTTP client, or at least the next middleware in the Rack stack.
126
- Most commonly this is a string, as in the above examples. But other values are
133
+ Most commonly, this is a string, as in the above examples. But other values are
127
134
  also accepted.
128
135
 
129
136
  You can return any object that would either be a valid Rack response, Rack
@@ -134,7 +141,7 @@ body object or HTTP status code:
134
141
  * An object that responds to <tt>#each</tt> and passes nothing but strings to the given block
135
142
  * A Fixnum representing the status code
136
143
 
137
- That way we can for instance easily implement a streaming example:
144
+ That way we can, for instance, easily implement a streaming example:
138
145
 
139
146
  class Stream
140
147
  def each
@@ -144,6 +151,47 @@ That way we can for instance easily implement a streaming example:
144
151
 
145
152
  get('/') { Stream.new }
146
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
+ @caputres = Match.new([])
166
+ end
167
+
168
+ def match(str)
169
+ @caputres 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
+
147
195
  == Static Files
148
196
 
149
197
  Static files are served from the <tt>./public</tt> directory. You can specify
@@ -164,15 +212,15 @@ directory. To use a different views directory:
164
212
 
165
213
  One important thing to remember is that you always have to reference
166
214
  templates with symbols, even if they're in a subdirectory (in this
167
- case use <tt>:'subdir/template'</tt>). You must use a symbol because
168
- otherwise rendering methods will render any strings passed to them
215
+ case, use <tt>:'subdir/template'</tt>). You must use a symbol because
216
+ otherwise rendering methods will render any strings passed to them
169
217
  directly.
170
218
 
171
219
  === Haml Templates
172
220
 
173
221
  The <tt>haml</tt> gem/library is required to render HAML templates:
174
222
 
175
- ## You'll need to require haml in your app
223
+ # You'll need to require haml in your app
176
224
  require 'haml'
177
225
 
178
226
  get '/' do
@@ -195,7 +243,7 @@ and overridden on an individual basis.
195
243
 
196
244
  === Erb Templates
197
245
 
198
- ## You'll need to require erb in your app
246
+ # You'll need to require erb in your app
199
247
  require 'erb'
200
248
 
201
249
  get '/' do
@@ -208,7 +256,7 @@ Renders <tt>./views/index.erb</tt>.
208
256
 
209
257
  The <tt>erubis</tt> gem/library is required to render Erubis templates:
210
258
 
211
- ## You'll need to require erubis in your app
259
+ # You'll need to require erubis in your app
212
260
  require 'erubis'
213
261
 
214
262
  get '/' do
@@ -232,7 +280,7 @@ Renders <tt>./views/index.erb</tt> with Erubis.
232
280
 
233
281
  The <tt>builder</tt> gem/library is required to render builder templates:
234
282
 
235
- ## You'll need to require builder in your app
283
+ # You'll need to require builder in your app
236
284
  require 'builder'
237
285
 
238
286
  get '/' do
@@ -245,7 +293,7 @@ Renders <tt>./views/index.builder</tt>.
245
293
 
246
294
  The <tt>nokogiri</tt> gem/library is required to render nokogiri templates:
247
295
 
248
- ## You'll need to require nokogiri in your app
296
+ # You'll need to require nokogiri in your app
249
297
  require 'nokogiri'
250
298
 
251
299
  get '/' do
@@ -258,7 +306,7 @@ Renders <tt>./views/index.nokogiri</tt>.
258
306
 
259
307
  The <tt>haml</tt> or <tt>sass</tt> gem/library is required to render Sass templates:
260
308
 
261
- ## You'll need to require haml or sass in your app
309
+ # You'll need to require haml or sass in your app
262
310
  require 'sass'
263
311
 
264
312
  get '/stylesheet.css' do
@@ -267,7 +315,7 @@ The <tt>haml</tt> or <tt>sass</tt> gem/library is required to render Sass templa
267
315
 
268
316
  Renders <tt>./views/stylesheet.sass</tt>.
269
317
 
270
- {Sass' options}[http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#options]
318
+ {Sass's options}[http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#options]
271
319
  can be set globally through Sinatra's configurations,
272
320
  see {Options and Configurations}[http://www.sinatrarb.com/configuration.html],
273
321
  and overridden on an individual basis.
@@ -282,7 +330,7 @@ and overridden on an individual basis.
282
330
 
283
331
  The <tt>haml</tt> or <tt>sass</tt> gem/library is required to render Scss templates:
284
332
 
285
- ## You'll need to require haml or sass in your app
333
+ # You'll need to require haml or sass in your app
286
334
  require 'sass'
287
335
 
288
336
  get '/stylesheet.css' do
@@ -291,7 +339,7 @@ The <tt>haml</tt> or <tt>sass</tt> gem/library is required to render Scss templa
291
339
 
292
340
  Renders <tt>./views/stylesheet.scss</tt>.
293
341
 
294
- {Scss' options}[http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#options]
342
+ {Scss's options}[http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#options]
295
343
  can be set globally through Sinatra's configurations,
296
344
  see {Options and Configurations}[http://www.sinatrarb.com/configuration.html],
297
345
  and overridden on an individual basis.
@@ -306,7 +354,7 @@ and overridden on an individual basis.
306
354
 
307
355
  The <tt>less</tt> gem/library is required to render Less templates:
308
356
 
309
- ## You'll need to require less in your app
357
+ # You'll need to require less in your app
310
358
  require 'less'
311
359
 
312
360
  get '/stylesheet.css' do
@@ -319,7 +367,7 @@ Renders <tt>./views/stylesheet.less</tt>.
319
367
 
320
368
  The <tt>liquid</tt> gem/library is required to render Liquid templates:
321
369
 
322
- ## You'll need to require liquid in your app
370
+ # You'll need to require liquid in your app
323
371
  require 'liquid'
324
372
 
325
373
  get '/' do
@@ -337,7 +385,7 @@ template, you almost always want to pass locals to it:
337
385
 
338
386
  The <tt>rdiscount</tt> gem/library is required to render Markdown templates:
339
387
 
340
- ## You'll need to require rdiscount in your app
388
+ # You'll need to require rdiscount in your app
341
389
  require "rdiscount"
342
390
 
343
391
  get '/' do
@@ -358,6 +406,28 @@ Note that you may also call the +markdown+ method from within other templates:
358
406
  %h1 Hello From Haml!
359
407
  %p= markdown(:greetings)
360
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
+
361
431
  It is also possible to parse Markdown with BlueCloth rather than RDiscount:
362
432
 
363
433
  require 'bluecloth'
@@ -376,7 +446,7 @@ Renders <tt>./views/index.md</tt> with BlueCloth.
376
446
 
377
447
  The <tt>RedCloth</tt> gem/library is required to render Textile templates:
378
448
 
379
- ## You'll need to require redcloth in your app
449
+ # You'll need to require redcloth in your app
380
450
  require "redcloth"
381
451
 
382
452
  get '/' do
@@ -395,12 +465,34 @@ Note that you may also call the +textile+ method from within other templates:
395
465
  %h1 Hello From Haml!
396
466
  %p= textile(:greetings)
397
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
+
398
490
  === RDoc Templates
399
491
 
400
492
  The <tt>rdoc</tt> gem/library is required to render RDoc templates:
401
493
 
402
- ## You'll need to require rdoc in your app
403
- require "rdoc"
494
+ # You'll need to require rdoc/markup/to_html in your app
495
+ require "rdoc/markup/to_html"
404
496
 
405
497
  get '/' do
406
498
  rdoc :index
@@ -418,11 +510,33 @@ Note that you may also call the +rdoc+ method from within other templates:
418
510
  %h1 Hello From Haml!
419
511
  %p= rdoc(:greetings)
420
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
+
421
535
  === Radius Templates
422
536
 
423
537
  The <tt>radius</tt> gem/library is required to render Radius templates:
424
538
 
425
- ## You'll need to require radius in your app
539
+ # You'll need to require radius in your app
426
540
  require 'radius'
427
541
 
428
542
  get '/' do
@@ -440,7 +554,7 @@ template, you almost always want to pass locals to it:
440
554
 
441
555
  The <tt>markaby</tt> gem/library is required to render Markaby templates:
442
556
 
443
- ## You'll need to require markaby in your app
557
+ # You'll need to require markaby in your app
444
558
  require 'markaby'
445
559
 
446
560
  get '/' do
@@ -449,6 +563,25 @@ The <tt>markaby</tt> gem/library is required to render Markaby templates:
449
563
 
450
564
  Renders <tt>./views/index.mab</tt>.
451
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
+
452
585
  === CoffeeScript Templates
453
586
 
454
587
  The <tt>coffee-script</tt> gem/library and at least <b>one</b> of the
@@ -462,7 +595,7 @@ See http://github.com/josh/ruby-coffee-script for an updated list of options.
462
595
 
463
596
  Now you can render CoffeeScript templates:
464
597
 
465
- ## You'll need to require coffee-script in your app
598
+ # You'll need to require coffee-script in your app
466
599
  require 'coffee-script'
467
600
 
468
601
  get '/application.js' do
@@ -482,7 +615,7 @@ Renders the embedded template string.
482
615
  === Accessing Variables in Templates
483
616
 
484
617
  Templates are evaluated within the same context as route handlers. Instance
485
- variables set in route handlers are direcly accessible by templates:
618
+ variables set in route handlers are directly accessible by templates:
486
619
 
487
620
  get '/:id' do
488
621
  @foo = Foo.find(params[:id])
@@ -554,7 +687,7 @@ To associate a file extension with a template engine, use
554
687
 
555
688
  Tilt.register :tt, Tilt[:textile]
556
689
 
557
- === Adding You Own Template Engine
690
+ === Adding Your Own Template Engine
558
691
 
559
692
  First, register your engine with Tilt, then create a rendering method:
560
693
 
@@ -571,26 +704,11 @@ First, register your engine with Tilt, then create a rendering method:
571
704
  Renders <tt>./views/index.myat</tt>. See https://github.com/rtomayko/tilt to
572
705
  learn more about Tilt.
573
706
 
574
- == Helpers
575
-
576
- Use the top-level <tt>helpers</tt> method to define helper methods for use in
577
- route handlers and templates:
578
-
579
- helpers do
580
- def bar(name)
581
- "#{name}bar"
582
- end
583
- end
584
-
585
- get '/:name' do
586
- bar(params[:name])
587
- end
588
-
589
707
  == Filters
590
708
 
591
- Before filters are evaluated before each request within the same context as
592
- the routes will be and can modify the request and response. Instance variables
593
- set in filters are accessible by routes and templates:
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:
594
712
 
595
713
  before do
596
714
  @note = 'Hi!'
@@ -602,7 +720,7 @@ set in filters are accessible by routes and templates:
602
720
  params[:splat] #=> 'bar/baz'
603
721
  end
604
722
 
605
- After filter are evaluated after each request within the same context and can
723
+ After filters are evaluated after each request within the same context and can
606
724
  also modify the request and response. Instance variables set in before filters
607
725
  and routes are accessible by after filters:
608
726
 
@@ -610,11 +728,11 @@ and routes are accessible by after filters:
610
728
  puts response.status
611
729
  end
612
730
 
613
- Note: Unless you use the `body` method rather than just returning a String from
731
+ Note: Unless you use the +body+ method rather than just returning a String from
614
732
  the routes, the body will not yet be available in the after filter, since it is
615
733
  generated later on.
616
734
 
617
- Filters optionally taking a pattern, causing them to be evaluated only if the
735
+ Filters optionally take a pattern, causing them to be evaluated only if the
618
736
  request path matches that pattern:
619
737
 
620
738
  before '/protected/*' do
@@ -625,7 +743,63 @@ request path matches that pattern:
625
743
  session[:last_slug] = slug
626
744
  end
627
745
 
628
- == Halting
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
+ === Halting
629
803
 
630
804
  To immediately stop a request within a filter or route use:
631
805
 
@@ -647,7 +821,11 @@ With headers:
647
821
 
648
822
  halt 402, {'Content-Type' => 'text/plain'}, 'revenge'
649
823
 
650
- == Passing
824
+ It is of course possible to combine a template with +halt+:
825
+
826
+ halt erb(:error)
827
+
828
+ === Passing
651
829
 
652
830
  A route can punt processing to the next matching route using <tt>pass</tt>:
653
831
 
@@ -663,9 +841,222 @@ A route can punt processing to the next matching route using <tt>pass</tt>:
663
841
  The route block is immediately exited and control continues with the next
664
842
  matching route. If no matching route is found, a 404 is returned.
665
843
 
666
- == Accessing the Request Object
844
+ === Triggering Another Route
845
+
846
+ Sometimes +pass+ is not what you want, instead you would like to get the result
847
+ of calling another route. Simply use +call+ to achieve this:
848
+
849
+ get '/foo' do
850
+ status, headers, body = call request.env.merge("PATH_INFO" => '/bar')
851
+ [status, body.upcase]
852
+ end
853
+
854
+ get '/bar' do
855
+ "bar"
856
+ end
857
+
858
+ Note that in the example above, you would ease testing and increase performance
859
+ by simply moving <tt>"bar"</tt> into a helper used by both <tt>/foo</tt>
860
+ and <tt>/bar</tt>.
861
+
862
+ If you want the request to be sent to the same application instance rather than
863
+ a duplicate, use <tt>call!</tt> instead of <tt>call</tt>.
864
+
865
+ Check out the Rack specification if you want to learn more about <tt>call</tt>.
866
+
867
+ === Setting Body, Status Code and Headers
868
+
869
+ It is possible and recommended to set the status code and response body with the
870
+ return value of the route block. However, in some scenarios you might want to
871
+ set the body at an arbitrary point in the execution flow. You can do so with the
872
+ +body+ helper method. If you do so, you can use that method from there on to
873
+ access the body:
874
+
875
+ get '/foo' do
876
+ body "bar"
877
+ end
878
+
879
+ after do
880
+ puts body
881
+ end
882
+
883
+ It is also possible to pass a block to +body+, which will be executed by the Rack
884
+ handler (this can be used to implement streaming, see "Return Values").
885
+
886
+ Similar to the body, you can also set the status code and headers:
887
+
888
+ get '/foo' do
889
+ status 418
890
+ headers \
891
+ "Allow" => "BREW, POST, GET, PROPFIND, WHEN"
892
+ "Refresh" => "Refresh: 20; http://www.ietf.org/rfc/rfc2324.txt"
893
+ body "I'm a tea pot!"
894
+ end
895
+
896
+ Like +body+, +headers+ and +status+ with no arguments can be used to access
897
+ their current values.
898
+
899
+ === Mime Types
900
+
901
+ When using <tt>send_file</tt> or static files you may have mime types Sinatra
902
+ doesn't understand. Use +mime_type+ to register them by file extension:
903
+
904
+ mime_type :foo, 'text/foo'
905
+
906
+ You can also use it with the +content_type+ helper:
907
+
908
+ get '/' do
909
+ content_type :foo
910
+ "foo foo foo"
911
+ end
912
+
913
+ === Generating URLs
914
+
915
+ For generating URLs you should use the +url+ helper method, for instance, in
916
+ Haml:
917
+
918
+ %a{:href => url('/foo')} foo
919
+
920
+ It takes reverse proxies and Rack routers into account, if present.
921
+
922
+ This method is also aliased to +to+ (see below for an example).
923
+
924
+ === Browser Redirect
925
+
926
+ You can trigger a browser redirect with the +redirect+ helper method:
927
+
928
+ get '/foo' do
929
+ redirect to('/bar')
930
+ end
931
+
932
+ Any additional parameters are handled like arguments passed to +halt+:
933
+
934
+ redirect to('/bar'), 303
935
+ redirect 'http://google.com', 'wrong place, buddy'
936
+
937
+ You can also easily redirect back to the page the user came from with
938
+ <tt>redirect back</tt>:
939
+
940
+ get '/foo' do
941
+ "<a href='/bar'>do something</a>"
942
+ end
943
+
944
+ get '/bar' do
945
+ do_something
946
+ redirect back
947
+ end
948
+
949
+ To pass arguments with a redirect, either add them to the query:
950
+
951
+ redirect to('/bar?sum=42')
952
+
953
+ Or use a session:
954
+
955
+ enable :session
956
+
957
+ get '/foo' do
958
+ session[:secret] = 'foo'
959
+ redirect to('/bar')
960
+ end
961
+
962
+ get '/bar' do
963
+ session[:secret]
964
+ end
965
+
966
+ === Cache Control
967
+
968
+ Setting your headers correctly is the foundation for proper HTTP caching.
969
+
970
+ You can easily set the Cache-Control header with like this:
971
+
972
+ get '/' do
973
+ cache_control :public
974
+ "cache it!"
975
+ end
976
+
977
+ Pro tip: Set up caching in a before filter.
978
+
979
+ before do
980
+ cache_control :public, :must_revalidate, :max_age => 60
981
+ end
982
+
983
+ If you are using the +expires+ helper to set the corresponding header,
984
+ <tt>Cache-Control</tt> will be set automatically for you:
985
+
986
+ before do
987
+ expires 500, :public, :must_revalidate
988
+ end
989
+
990
+ To properly use caches, you should consider using +etag+ and +last_modified+.
991
+ It is recommended to call those helpers *before* doing heavy lifting, as they
992
+ will immediately flush a response if the client already has the current
993
+ version in its cache.
994
+
995
+ get '/article/:id' do
996
+ @article = Article.find params[:id]
997
+ last_modified @article.updated_at
998
+ etag @article.sha1
999
+ erb :article
1000
+ end
1001
+
1002
+ It is also possible to use a
1003
+ {weak ETag}[http://en.wikipedia.org/wiki/HTTP_ETag#Strong_and_weak_validation]:
1004
+
1005
+ etag @article.sha1, :weak
1006
+
1007
+ These helpers will not do any caching for you, but rather feed the necessary
1008
+ information to your cache. If you are looking for a quick caching solutions, try
1009
+ {rack-cache}[http://rtomayko.github.com/rack-cache/]:
1010
+
1011
+ require "rack/cache"
1012
+ require "sinatra"
1013
+
1014
+ use Rack::Cache
1015
+
1016
+ get '/' do
1017
+ cache_control :public, :max_age => 36000
1018
+ sleep 5
1019
+ "hello"
1020
+ end
1021
+
1022
+ === Sending Files
1023
+
1024
+ For sending files, you can use the <tt>send_file</tt> helper method:
1025
+
1026
+ get '/' do
1027
+ send_file 'foo.png'
1028
+ end
1029
+
1030
+ It also takes a couple of options:
1031
+
1032
+ send_file 'foo.png', :type => :jpg
1033
+
1034
+ The options are:
1035
+
1036
+ [filename]
1037
+ file name, in response, defaults to the real file name.
1038
+
1039
+ [last_modified]
1040
+ value for Last-Modified header, defaults to the file's mtime.
1041
+
1042
+ [type]
1043
+ content type to use, guessed from the file extension if missing.
1044
+
1045
+ [disposition]
1046
+ used for Content-Disposition, possible values: +nil+ (default),
1047
+ <tt>:attachment</tt> and <tt>:inline</tt>
1048
+
1049
+ [length]
1050
+ Content-Length header, defaults to file size.
1051
+
1052
+ If supported by the Rack handler, other means than streaming from the Ruby
1053
+ process will be used. If you use this helper method, Sinatra will automatically
1054
+ handle range requests.
1055
+
1056
+ === Accessing the Request Object
667
1057
 
668
- The incoming request object can be accessed from request level (filter, routes, error handlers) through the `request` method:
1058
+ The incoming request object can be accessed from request level (filter, routes,
1059
+ error handlers) through the <tt>request</tt> method:
669
1060
 
670
1061
  # app running on http://example.com/example
671
1062
  get '/foo' do
@@ -682,18 +1073,19 @@ The incoming request object can be accessed from request level (filter, routes,
682
1073
  request.get? # true (similar methods for other verbs)
683
1074
  request.form_data? # false
684
1075
  request["SOME_HEADER"] # value of SOME_HEADER header
685
- request.referer # the referer of the client or '/'
1076
+ request.referrer # the referrer of the client or '/'
686
1077
  request.user_agent # user agent (used by :agent condition)
687
1078
  request.cookies # hash of browser cookies
688
1079
  request.xhr? # is this an ajax request?
689
1080
  request.url # "http://example.com/example/foo"
690
1081
  request.path # "/example/foo"
691
1082
  request.ip # client IP address
692
- request.secure? # false
1083
+ request.secure? # false (would be true over ssl)
1084
+ request.forwarded? # true (if running behind a reverse proxy)
693
1085
  request.env # raw env hash handed in by Rack
694
1086
  end
695
1087
 
696
- Some options, like <tt>script_name</tt> or <tt>path_info</tt> can also be
1088
+ Some options, like <tt>script_name</tt> or <tt>path_info</tt>, can also be
697
1089
  written:
698
1090
 
699
1091
  before { request.path_info = "/" }
@@ -710,6 +1102,64 @@ The <tt>request.body</tt> is an IO or StringIO object:
710
1102
  "Hello #{data['name']}!"
711
1103
  end
712
1104
 
1105
+ === Attachments
1106
+
1107
+ You can use the +attachment+ helper to tell the browser the response should be
1108
+ stored on disk rather than displayed in the browser.
1109
+
1110
+ get '/' do
1111
+ attachment
1112
+ "store it!"
1113
+ end
1114
+
1115
+ You can also pass it a file name:
1116
+
1117
+ get '/' do
1118
+ attachment "info.txt"
1119
+ "store it!"
1120
+ end
1121
+
1122
+ === Looking Up Template Files
1123
+
1124
+ The <tt>find_template</tt> helper is used to find template files for rendering:
1125
+
1126
+ find_template settings.views, 'foo', Tilt[:haml] do |file|
1127
+ puts "could be #{file}"
1128
+ end
1129
+
1130
+ This is not really useful. But it is useful that you can actually override this
1131
+ method to hook in your own lookup mechanism. For instance, if you want to be
1132
+ able to use more than one view directory:
1133
+
1134
+ set :views, ['views', 'templates']
1135
+
1136
+ helpers do
1137
+ def find_template(views, name, engine, &block)
1138
+ Array(views).each { |v| super(v, name, engine, &block) }
1139
+ end
1140
+ end
1141
+
1142
+ Another example would be using different directories for different engines:
1143
+
1144
+ set :views, :sass => 'views/sass', :haml => 'templates', :default => 'views'
1145
+
1146
+ helpers do
1147
+ def find_template(views, name, engine, &block)
1148
+ _, folder = views.detect { |k,v| engine == Tilt[k] }
1149
+ folder ||= views[:default]
1150
+ super(folder, name, engine, &block)
1151
+ end
1152
+ end
1153
+
1154
+ You can also easily wrap this up in an extension and share with others!
1155
+
1156
+ Note that <tt>find_template</tt> does not check if the file really exists but
1157
+ rather calls the given block for all possible paths. This is not a performance
1158
+ issue, since +render+ will use +break+ as soon as a file is found. Also,
1159
+ template locations (and content) will be cached if you are not running in
1160
+ development mode. You should keep that in mind if you write a really crazy
1161
+ method.
1162
+
713
1163
  == Configuration
714
1164
 
715
1165
  Run once, at startup, in any environment:
@@ -757,6 +1207,89 @@ You can access those options via <tt>settings</tt>:
757
1207
  ...
758
1208
  end
759
1209
 
1210
+ === Available Settings
1211
+
1212
+ [absolute_redirects] If disabled, Sinatra will allow relative redirects,
1213
+ however, Sinatra will no longer conform with RFC 2616
1214
+ (HTTP 1.1), which only allows absolute redirects.
1215
+
1216
+ Enable if your app is running behind a reverse proxy that
1217
+ has not been set up properly. Note that the +url+ helper
1218
+ will still produce absolute URLs, unless you pass in
1219
+ +false+ as second parameter.
1220
+
1221
+ Disabled per default.
1222
+
1223
+ [add_charsets] mime types the <tt>content_type</tt> helper will
1224
+ automatically add the charset info to.
1225
+
1226
+ You should add to it rather than overriding this option:
1227
+
1228
+ settings.add_charsets << "application/foobar"
1229
+
1230
+ [app_file] main application file, used to detect project root,
1231
+ views and public folder and inline templates.
1232
+
1233
+ [bind] IP address to bind to (default: 0.0.0.0).
1234
+ Only used for built-in server.
1235
+
1236
+ [default_encoding] encoding to assume if unknown
1237
+ (defaults to <tt>"utf-8"</tt>).
1238
+
1239
+ [dump_errors] display errors in the log.
1240
+
1241
+ [environment] current environment, defaults to <tt>ENV['RACK_ENV']</tt>,
1242
+ or <tt>"development"</tt> if not available.
1243
+
1244
+ [logging] use the logger.
1245
+
1246
+ [lock] Places a lock around every request, only running
1247
+ processing on request per Ruby process concurrently.
1248
+
1249
+ Enabled if your app is not thread-safe.
1250
+ Disabled per default.
1251
+
1252
+ [method_override] use <tt>_method</tt> magic to allow put/delete forms in
1253
+ browsers that don't support it.
1254
+
1255
+ [port] Port to listen on. Only used for built-in server.
1256
+
1257
+ [prefixed_redirects] Whether or not to insert <tt>request.script_name</tt> into
1258
+ redirects if no absolute path is given. That way
1259
+ <tt>redirect '/foo'</tt> would behave like
1260
+ <tt>redirect to('/foo')</tt>. Disabled per default.
1261
+
1262
+ [public] folder public files are served from
1263
+
1264
+ [reload_templates] whether or not to reload templates between requests.
1265
+ Enabled in development mode and on Ruby 1.8.6 (to
1266
+ compensate a bug in Ruby causing a memory leak).
1267
+
1268
+ [root] project root folder.
1269
+
1270
+ [raise_errors] raise exceptions (will stop application).
1271
+
1272
+ [run] if enabled, Sinatra will handle starting the web server,
1273
+ do not enable if using rackup or other means.
1274
+
1275
+ [running] is the built-in server running now?
1276
+ do not change this setting!
1277
+
1278
+ [server] server or list of servers to use for built-in server.
1279
+ defaults to ['thin', 'mongrel', 'webrick'], order indicates
1280
+ priority.
1281
+
1282
+ [sessions] enable cookie based sessions.
1283
+
1284
+ [show_exceptions] show a stack trace in the browser.
1285
+
1286
+ [static] Whether Sinatra should handle serving static files.
1287
+ Disable when using a Server able to do this on its own.
1288
+ Disabling will boost performance.
1289
+ Enabled per default.
1290
+
1291
+ [views] views folder.
1292
+
760
1293
  == Error Handling
761
1294
 
762
1295
  Error handlers run within the same context as routes and before filters, which
@@ -798,7 +1331,7 @@ You get this:
798
1331
 
799
1332
  So what happened was... something bad
800
1333
 
801
- Alternatively, you can install error handler for a status code:
1334
+ Alternatively, you can install an error handler for a status code:
802
1335
 
803
1336
  error 403 do
804
1337
  'Access forbidden'
@@ -817,17 +1350,6 @@ Or a range:
817
1350
  Sinatra installs special <tt>not_found</tt> and <tt>error</tt> handlers when
818
1351
  running under the development environment.
819
1352
 
820
- == Mime Types
821
-
822
- When using <tt>send_file</tt> or static files you may have mime types Sinatra
823
- doesn't understand. Use +mime_type+ to register them by file extension:
824
-
825
- mime_type :foo, 'text/foo'
826
-
827
- You can also use it with the +content_type+ helper:
828
-
829
- content_type :foo
830
-
831
1353
  == Rack Middleware
832
1354
 
833
1355
  Sinatra rides on Rack[http://rack.rubyforge.org/], a minimal standard
@@ -860,7 +1382,7 @@ accepts multiple/variable args as well as blocks:
860
1382
 
861
1383
  Rack is distributed with a variety of standard middleware for logging,
862
1384
  debugging, URL routing, authentication, and session handling. Sinatra uses
863
- many of of these components automatically based on configuration so you
1385
+ many of these components automatically based on configuration so you
864
1386
  typically don't have to +use+ them explicitly.
865
1387
 
866
1388
  == Testing
@@ -924,7 +1446,7 @@ The methods available to Sinatra::Base subclasses are exactly as those
924
1446
  available via the top-level DSL. Most top-level apps can be converted to
925
1447
  Sinatra::Base components with two modifications:
926
1448
 
927
- * Your file should require +sinatra/base+ instead of +sinatra+;
1449
+ * Your file should require <tt>sinatra/base</tt> instead of +sinatra+;
928
1450
  otherwise, all of Sinatra's DSL methods are imported into the main
929
1451
  namespace.
930
1452
  * Put your app's routes, error handlers, filters, and options in a subclass
@@ -936,15 +1458,15 @@ for details on available options and their behavior.
936
1458
 
937
1459
  === Modular vs. Classic Style
938
1460
 
939
- Contrary to common believes, there is nothing wrong with classic style. If it
1461
+ Contrary to common belief, there is nothing wrong with classic style. If it
940
1462
  suits your application, you do not have to switch to a modular application.
941
1463
 
942
- There are only two downsides compared to modulare style:
1464
+ There are only two downsides compared with modular style:
943
1465
 
944
- * You may only have one Sinatra application per Ruby process - if you plan to
1466
+ * You may only have one Sinatra application per Ruby process. If you plan to
945
1467
  use more, switch to modular style.
946
1468
 
947
- * Classic style pollutes Object with delegator methods - if you plan to ship
1469
+ * Classic style pollutes Object with delegator methods. If you plan to ship
948
1470
  your application in a library/gem, switch to modular style.
949
1471
 
950
1472
  There is no reason you cannot mix modular and classic style.
@@ -963,7 +1485,7 @@ differences in the setting:
963
1485
 
964
1486
  === Serving a Modular Application
965
1487
 
966
- There are two common options for starting a modular app, activly starting with
1488
+ There are two common options for starting a modular app, actively starting with
967
1489
  <tt>run!</tt>:
968
1490
 
969
1491
  # my_app.rb
@@ -1063,13 +1585,13 @@ available.
1063
1585
  === Application/Class Scope
1064
1586
 
1065
1587
  Every Sinatra application corresponds to a subclass of Sinatra::Base. If you
1066
- are using the top level DSL (<tt>require 'sinatra'</tt>), then this class is
1588
+ are using the top-level DSL (<tt>require 'sinatra'</tt>), then this class is
1067
1589
  Sinatra::Application, otherwise it is the subclass you created explicitly. At
1068
- class level you have methods like `get` or `before`, but you cannot access the
1069
- `request` object or the `session`, as there only is a single application class
1590
+ class level you have methods like +get+ or +before+, but you cannot access the
1591
+ +request+ object or the +session+, as there only is a single application class
1070
1592
  for all requests.
1071
1593
 
1072
- Options created via `set` are methods at class level:
1594
+ Options created via +set+ are methods at class level:
1073
1595
 
1074
1596
  class MyApp < Sinatra::Base
1075
1597
  # Hey, I'm in the application scope!
@@ -1085,21 +1607,21 @@ You have the application scope binding inside:
1085
1607
 
1086
1608
  * Your application class body
1087
1609
  * Methods defined by extensions
1088
- * The block passed to `helpers`
1089
- * Procs/blocks used as value for `set`
1610
+ * The block passed to +helpers+
1611
+ * Procs/blocks used as value for +set+
1090
1612
 
1091
1613
  You can reach the scope object (the class) like this:
1092
1614
 
1093
1615
  * Via the object passed to configure blocks (<tt>configure { |c| ... }</tt>)
1094
- * `settings` from within request scope
1616
+ * +settings+ from within request scope
1095
1617
 
1096
1618
  === Request/Instance Scope
1097
1619
 
1098
1620
  For every incoming request, a new instance of your application class is
1099
1621
  created and all handler blocks run in that scope. From within this scope you
1100
- can access the `request` and `session` object or call rendering methods like
1101
- `erb` or `haml`. You can access the application scope from within the request
1102
- scope via the `settings` helper:
1622
+ can access the +request+ and +session+ object or call rendering methods like
1623
+ +erb+ or +haml+. You can access the application scope from within the request
1624
+ scope via the +settings+ helper:
1103
1625
 
1104
1626
  class MyApp < Sinatra::Base
1105
1627
  # Hey, I'm in the application scope!
@@ -1118,7 +1640,7 @@ scope via the `settings` helper:
1118
1640
 
1119
1641
  You have the request scope binding inside:
1120
1642
 
1121
- * get/head/post/put/delete blocks
1643
+ * get/head/post/put/delete/options blocks
1122
1644
  * before/after filters
1123
1645
  * helper methods
1124
1646
  * templates/views
@@ -1126,16 +1648,16 @@ You have the request scope binding inside:
1126
1648
  === Delegation Scope
1127
1649
 
1128
1650
  The delegation scope just forwards methods to the class scope. However, it
1129
- does not behave 100% like the class scope, as you do not have the class'
1130
- binding: Only methods explicitly marked for delegation are available and you
1651
+ does not behave 100% like the class scope, as you do not have the class
1652
+ binding. Only methods explicitly marked for delegation are available and you
1131
1653
  do not share variables/state with the class scope (read: you have a different
1132
- `self`). You can explicitly add method delegations by calling
1654
+ +self+). You can explicitly add method delegations by calling
1133
1655
  <tt>Sinatra::Delegator.delegate :method_name</tt>.
1134
1656
 
1135
1657
  You have the delegate scope binding inside:
1136
1658
 
1137
1659
  * The top level binding, if you did <tt>require "sinatra"</tt>
1138
- * An object extended with the `Sinatra::Delegator` mixin
1660
+ * An object extended with the <tt>Sinatra::Delegator</tt> mixin
1139
1661
 
1140
1662
  Have a look at the code for yourself: here's the
1141
1663
  {Sinatra::Delegator mixin}[http://github.com/sinatra/sinatra/blob/ceac46f0bc129a6e994a06100aa854f606fe5992/lib/sinatra/base.rb#L1128]
@@ -1156,6 +1678,57 @@ Options are:
1156
1678
  -s # specify rack server/handler (default is thin)
1157
1679
  -x # turn on the mutex lock (default is off)
1158
1680
 
1681
+ == Requirements
1682
+
1683
+ It is recommended to install Sinatra on Ruby 1.8.7, 1.9.2, JRuby or Rubinius.
1684
+
1685
+ The following Ruby versions are officially supported:
1686
+
1687
+ [ Ruby 1.8.6 ]
1688
+ It is not recommended to use 1.8.6 for Sinatra. However, it will be
1689
+ officially supported until Sinatra 1.3.0 is released. RDoc and CoffeScript
1690
+ templates are not supported by this Ruby version. 1.8.6 includes a major
1691
+ memory leak in its Hash implementation, which is triggered by Sinatra
1692
+ versions prior to 1.1.1. The current version explicitly prevents this leak
1693
+ at the cost of performance. You will have to downgrade Rack to 1.1.x, as
1694
+ Rack >= 1.2 no longer supports 1.8.6.
1695
+
1696
+ [ Ruby 1.8.7 ]
1697
+ 1.8.7 is fully supported, however, if nothing is keeping you from it, we
1698
+ recommend upgrading to 1.9.2 or switching to JRuby or Rubinius.
1699
+
1700
+ [ Ruby 1.9.2 ]
1701
+ 1.9.2 is supported and recommended. Note that Radius and Markaby are
1702
+ currently not 1.9 compatible. Do not use 1.9.2p0, it is known to cause
1703
+ segmentation faults when using Sinatra.
1704
+
1705
+ [ Rubinius ]
1706
+ Rubinius is officially supported (Rubinius >= 1.2.2), with the exception
1707
+ of Textile templates.
1708
+
1709
+ [ JRuby ]
1710
+ JRuby is officially supported (JRuby >= 1.5.6). No issues with third party
1711
+ template libraries are known, however, if you choose to use JRuby, please
1712
+ look into JRuby rack handlers, as the Thin web server is not (yet) supported
1713
+ on JRuby.
1714
+
1715
+ We also keep an eye on upcoming Ruby versions.
1716
+
1717
+ The following Ruby implementations are not officially supported but still are
1718
+ known to run Sinatra:
1719
+
1720
+ * Older versions of JRuby and Rubinius
1721
+ * MacRuby
1722
+ * Maglev
1723
+ * IronRuby
1724
+ * Ruby 1.9.0 and 1.9.1
1725
+
1726
+ Not being officially supported means if things only break there and not on a
1727
+ supported platform, we assume it's not our issue but theirs.
1728
+
1729
+ Sinatra should work on any operating system supported by the chosen Ruby
1730
+ implementation.
1731
+
1159
1732
  == The Bleeding Edge
1160
1733
  If you would like to use Sinatra's latest bleeding code, feel free to run your
1161
1734
  application against the master branch, it should be rather stable.
@@ -1168,13 +1741,13 @@ To get some of the latest features.
1168
1741
 
1169
1742
  === With Bundler
1170
1743
  If you want to run your application with the latest Sinatra, using
1171
- {Bundler}[http://gembundler.com/] is the recommend way.
1744
+ {Bundler}[http://gembundler.com/] is the recommended way.
1172
1745
 
1173
1746
  First, install bundler, if you haven't:
1174
1747
 
1175
1748
  gem install bundler
1176
1749
 
1177
- Then, in you project directory, create a +Gemfile+:
1750
+ Then, in your project directory, create a +Gemfile+:
1178
1751
 
1179
1752
  source :rubygems
1180
1753
  gem 'sinatra', :git => "git://github.com/sinatra/sinatra.git"
@@ -1184,7 +1757,7 @@ Then, in you project directory, create a +Gemfile+:
1184
1757
  gem 'activerecord', '~> 3.0' # maybe you also need ActiveRecord 3.x
1185
1758
 
1186
1759
  Note that you will have to list all your applications dependencies in there.
1187
- Sinatra's direct dependencies (Rack and Tilt) will however be automatically
1760
+ Sinatra's direct dependencies (Rack and Tilt) will, however, be automatically
1188
1761
  fetched and added by Bundler.
1189
1762
 
1190
1763
  Now you can run your app like this:
@@ -1193,7 +1766,7 @@ Now you can run your app like this:
1193
1766
 
1194
1767
  === Roll Your Own
1195
1768
  Create a local clone and run your app with the <tt>sinatra/lib</tt> directory
1196
- on the <tt>LOAD_PATH</tt>:
1769
+ on the <tt>$LOAD_PATH</tt>:
1197
1770
 
1198
1771
  cd myapp
1199
1772
  git clone git://github.com/sinatra/sinatra.git