3
Sinatra is a DSL for quickly creating web applications in Ruby with minimal
13
Install the gem and run with:
16
ruby -rubygems myapp.rb
18
View at: http://localhost:4567
20
It is recommended to also run <tt>gem install thin</tt>, which Sinatra will
25
In Sinatra, a route is an HTTP method paired with a URL-matching pattern.
26
Each route is associated with a block:
33
.. create something ..
37
.. update something ..
41
.. annihilate something ..
45
.. appease something ..
48
Routes are matched in the order they are defined. The first route that
49
matches the request is invoked.
51
Route patterns may include named parameters, accessible via the
55
# matches "GET /hello/foo" and "GET /hello/bar"
56
# params[:name] is 'foo' or 'bar'
57
"Hello #{params[:name]}!"
60
You can also access named parameters via block parameters:
62
get '/hello/:name' do |n|
66
Route patterns may also include splat (or wildcard) parameters, accessible
67
via the <tt>params[:splat]</tt> array:
70
# matches /say/hello/to/world
71
params[:splat] # => ["hello", "world"]
74
get '/download/*.*' do
75
# matches /download/path/to/file.xml
76
params[:splat] # => ["path/to/file", "xml"]
79
Route matching with Regular Expressions:
81
get %r{/hello/([\w]+)} do
82
"Hello, #{params[:captures].first}!"
85
Or with a block parameter:
87
get %r{/hello/([\w]+)} do |c|
93
Routes may include a variety of matching conditions, such as the user agent:
95
get '/foo', :agent => /Songbird (\d\.\d)[\d\/]*?/ do
96
"You're using Songbird version #{params[:agent][0]}"
100
# Matches non-songbird browsers
103
Other available conditions are +host_name+ and +provides+:
105
get '/', :host_name => /^admin\./ do
106
"Admin Area, Access denied!"
109
get '/', :provides => 'html' do
113
get '/', :provides => ['rss', 'atom', 'xml'] do
117
You can easily define your own conditions:
119
set(:probability) { |value| condition { rand <= value } }
121
get '/win_a_car', :probability => 0.1 do
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
136
You can return any object that would either be a valid Rack response, Rack
137
body object or HTTP status code:
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
144
That way we can, for instance, easily implement a streaming example:
148
100.times { |i| yield "#{i}\n" }
152
get('/') { Stream.new }
154
=== Custom Route Matchers
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:
161
Match = Struct.new(:captures)
163
def initialize(except)
165
@captures = Match.new([])
169
@captures unless @except === str
174
AllButPattern.new(pattern)
177
get all_but("/index") do
181
Note that the above example might be over-engineered, as it can also be
185
pass if request.path_info == "/index"
189
Or, using negative look ahead:
191
get %r{^(?!/index$)} do
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:
200
set :public, File.dirname(__FILE__) + '/static'
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>.
208
Templates are assumed to be located directly under the <tt>./views</tt>
209
directory. To use a different views directory:
211
set :views, File.dirname(__FILE__) + '/templates'
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
221
The <tt>haml</tt> gem/library is required to render HAML templates:
223
# You'll need to require haml in your app
230
Renders <tt>./views/index.haml</tt>.
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.
237
set :haml, :format => :html5 # default Haml format is :xhtml
240
haml :index, :format => :html4 # overridden
246
# You'll need to require erb in your app
253
Renders <tt>./views/index.erb</tt>.
257
The <tt>erubis</tt> gem/library is required to render Erubis templates:
259
# You'll need to require erubis in your app
266
Renders <tt>./views/index.erubis</tt>.
268
It is also possible to replace Erb with Erubis:
271
Tilt.register :erb, Tilt[:erubis]
277
Renders <tt>./views/index.erb</tt> with Erubis.
279
=== Builder Templates
281
The <tt>builder</tt> gem/library is required to render builder templates:
283
# You'll need to require builder in your app
290
Renders <tt>./views/index.builder</tt>.
292
=== Nokogiri Templates
294
The <tt>nokogiri</tt> gem/library is required to render nokogiri templates:
296
# You'll need to require nokogiri in your app
303
Renders <tt>./views/index.nokogiri</tt>.
307
The <tt>haml</tt> or <tt>sass</tt> gem/library is required to render Sass templates:
309
# You'll need to require haml or sass in your app
312
get '/stylesheet.css' do
316
Renders <tt>./views/stylesheet.sass</tt>.
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.
323
set :sass, :style => :compact # default Sass style is :nested
325
get '/stylesheet.css' do
326
sass :stylesheet, :style => :expanded # overridden
331
The <tt>haml</tt> or <tt>sass</tt> gem/library is required to render Scss templates:
333
# You'll need to require haml or sass in your app
336
get '/stylesheet.css' do
340
Renders <tt>./views/stylesheet.scss</tt>.
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.
347
set :scss, :style => :compact # default Scss style is :nested
349
get '/stylesheet.css' do
350
scss :stylesheet, :style => :expanded # overridden
355
The <tt>less</tt> gem/library is required to render Less templates:
357
# You'll need to require less in your app
360
get '/stylesheet.css' do
364
Renders <tt>./views/stylesheet.less</tt>.
368
The <tt>liquid</tt> gem/library is required to render Liquid templates:
370
# You'll need to require liquid in your app
377
Renders <tt>./views/index.liquid</tt>.
379
Since you cannot call Ruby methods (except for +yield+) from a Liquid
380
template, you almost always want to pass locals to it:
382
liquid :index, :locals => { :key => 'value' }
384
=== Markdown Templates
386
The <tt>rdiscount</tt> gem/library is required to render Markdown templates:
388
# You'll need to require rdiscount in your app
395
Renders <tt>./views/index.markdown</tt> (+md+ and +mkd+ are also valid file
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
402
erb :overview, :locals => { :text => markdown(:introduction) }
404
Note that you may also call the +markdown+ method from within other templates:
407
%p= markdown(:greetings)
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:
414
markdown :index, :layout_engine => :erb
417
This will render <tt>./views/index.md</tt> with <tt>./views/layout.erb</tt> as
420
Remember that you can set such rendering options globally:
422
set :markdown, :layout_engine => :haml, :layout => :post
428
This will render <tt>./views/index.md</tt> (and any other Markdown template)
429
with <tt>./views/post.haml</tt> as layout.
431
It is also possible to parse Markdown with BlueCloth rather than RDiscount:
435
Tilt.register 'markdown', BlueClothTemplate
436
Tilt.register 'mkd', BlueClothTemplate
437
Tilt.register 'md', BlueClothTemplate
443
Renders <tt>./views/index.md</tt> with BlueCloth.
445
=== Textile Templates
447
The <tt>RedCloth</tt> gem/library is required to render Textile templates:
449
# You'll need to require redcloth in your app
456
Renders <tt>./views/index.textile</tt>.
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:
461
erb :overview, :locals => { :text => textile(:introduction) }
463
Note that you may also call the +textile+ method from within other templates:
466
%p= textile(:greetings)
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:
473
textile :index, :layout_engine => :erb
476
This will render <tt>./views/index.textile</tt> with
477
<tt>./views/layout.erb</tt> as layout.
479
Remember that you can set such rendering options globally:
481
set :textile, :layout_engine => :haml, :layout => :post
487
This will render <tt>./views/index.textile</tt> (and any other Textile
488
template) with <tt>./views/post.haml</tt> as layout.
492
The <tt>rdoc</tt> gem/library is required to render RDoc templates:
494
# You'll need to require rdoc/markup/to_html in your app
495
require "rdoc/markup/to_html"
501
Renders <tt>./views/index.rdoc</tt>.
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:
506
erb :overview, :locals => { :text => rdoc(:introduction) }
508
Note that you may also call the +rdoc+ method from within other templates:
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:
518
rdoc :index, :layout_engine => :erb
521
This will render <tt>./views/index.rdoc</tt> with <tt>./views/layout.erb</tt> as
524
Remember that you can set such rendering options globally:
526
set :rdoc, :layout_engine => :haml, :layout => :post
532
This will render <tt>./views/index.rdoc</tt> (and any other RDoc template)
533
with <tt>./views/post.haml</tt> as layout.
537
The <tt>radius</tt> gem/library is required to render Radius templates:
539
# You'll need to require radius in your app
546
Renders <tt>./views/index.radius</tt>.
548
Since you cannot call Ruby methods (except for +yield+) from a Radius
549
template, you almost always want to pass locals to it:
551
radius :index, :locals => { :key => 'value' }
553
=== Markaby Templates
555
The <tt>markaby</tt> gem/library is required to render Markaby templates:
557
# You'll need to require markaby in your app
564
Renders <tt>./views/index.mab</tt>.
566
You may also use inline Markaby:
569
markaby { h1 "Welcome!" }
574
The <tt>slim</tt> gem/library is required to render Slim templates:
576
# You'll need to require slim in your app
583
Renders <tt>./views/index.slim</tt>.
585
=== CoffeeScript Templates
587
The <tt>coffee-script</tt> gem/library and at least <b>one</b> of the
588
following options to execute JavaScript:
590
* +node+ (from Node.js) in your path
591
* you must be running on OSX
592
* +therubyracer+ gem/library
594
See http://github.com/josh/ruby-coffee-script for an updated list of options.
596
Now you can render CoffeeScript templates:
598
# You'll need to require coffee-script in your app
599
require 'coffee-script'
601
get '/application.js' do
605
Renders <tt>./views/application.coffee</tt>.
607
=== Embedded Templates
610
haml '%div.title Hello World'
613
Renders the embedded template string.
615
=== Accessing Variables in Templates
617
Templates are evaluated within the same context as route handlers. Instance
618
variables set in route handlers are directly accessible by templates:
621
@foo = Foo.find(params[:id])
622
haml '%h1= @foo.name'
625
Or, specify an explicit Hash of local variables:
628
foo = Foo.find(params[:id])
629
haml '%h1= foo.name', :locals => { :foo => foo }
632
This is typically used when rendering templates as partials from within
637
Templates may be defined at the end of the source file:
652
%div.title Hello world!!!!!
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.
660
Templates may also be defined using the top-level <tt>template</tt> method:
667
'%div.title Hello World!'
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>:
679
haml :index, :layout => !request.xhr?
682
=== Associating File Extensions
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:
688
Tilt.register :tt, Tilt[:textile]
690
=== Adding Your Own Template Engine
692
First, register your engine with Tilt, then create a rendering method:
694
Tilt.register :myat, MyAwesomeTemplateEngine
697
def myat(*args) render(:myat, *args) end
704
Renders <tt>./views/index.myat</tt>. See https://github.com/rtomayko/tilt to
705
learn more about Tilt.
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:
715
request.path_info = '/foo/bar/baz'
720
params[:splat] #=> 'bar/baz'
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:
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
735
Filters optionally take a pattern, causing them to be evaluated only if the
736
request path matches that pattern:
738
before '/protected/*' do
742
after '/create/:slug' do |slug|
743
session[:last_slug] = slug
746
Like routes, filters also take conditions:
748
before :agent => /Songbird/ do
752
after '/blog/*', :host_name => 'example.com' do
758
Use the top-level <tt>helpers</tt> method to define helper methods for use in
759
route handlers and templates:
773
A session is used to keep state during requests. If activated, you have one
774
session hash per user session:
779
"value = " << session[:value].inspect
783
session[:value] = params[:value]
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:
792
use Rack::Session::Pool, :expire_after => 2592000
795
"value = " << session[:value].inspect
799
session[:value] = params[:value]
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:
807
set :session_secret, 'super secret'
811
To immediately stop a request within a filter or route use:
815
You can also specify the status when halting:
821
halt 'this will be the body'
829
halt 402, {'Content-Type' => 'text/plain'}, 'revenge'
831
It is of course possible to combine a template with +halt+:
837
A route can punt processing to the next matching route using <tt>pass</tt>:
840
pass unless params[:who] == 'Frank'
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.
851
=== Triggering Another Route
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:
857
status, headers, body = call request.env.merge("PATH_INFO" => '/bar')
858
[status, body.upcase]
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>
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>.
872
Check out the Rack specification if you want to learn more about <tt>call</tt>.
874
=== Setting Body, Status Code and Headers
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
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").
893
Similar to the body, you can also set the status code and 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!"
903
Like +body+, +headers+ and +status+ with no arguments can be used to access
904
their current values.
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:
911
mime_type :foo, 'text/foo'
913
You can also use it with the +content_type+ helper:
922
For generating URLs you should use the +url+ helper method, for instance, in
925
%a{:href => url('/foo')} foo
927
It takes reverse proxies and Rack routers into account, if present.
929
This method is also aliased to +to+ (see below for an example).
933
You can trigger a browser redirect with the +redirect+ helper method:
939
Any additional parameters are handled like arguments passed to +halt+:
941
redirect to('/bar'), 303
942
redirect 'http://google.com', 'wrong place, buddy'
944
You can also easily redirect back to the page the user came from with
945
<tt>redirect back</tt>:
948
"<a href='/bar'>do something</a>"
956
To pass arguments with a redirect, either add them to the query:
958
redirect to('/bar?sum=42')
965
session[:secret] = 'foo'
975
Setting your headers correctly is the foundation for proper HTTP caching.
977
You can easily set the Cache-Control header with like this:
980
cache_control :public
984
Pro tip: Set up caching in a before filter:
987
cache_control :public, :must_revalidate, :max_age => 60
990
If you are using the +expires+ helper to set the corresponding header,
991
<tt>Cache-Control</tt> will be set automatically for you:
994
expires 500, :public, :must_revalidate
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:
1002
get '/article/:id' do
1003
@article = Article.find params[:id]
1004
last_modified @article.updated_at
1009
It is also possible to use a
1010
{weak ETag}[http://en.wikipedia.org/wiki/HTTP_ETag#Strong_and_weak_validation]:
1012
etag @article.sha1, :weak
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/]:
1018
require "rack/cache"
1024
cache_control :public, :max_age => 36000
1031
For sending files, you can use the <tt>send_file</tt> helper method:
1037
It also takes a couple of options:
1039
send_file 'foo.png', :type => :jpg
1044
file name, in response, defaults to the real file name.
1047
value for Last-Modified header, defaults to the file's mtime.
1050
content type to use, guessed from the file extension if missing.
1053
used for Content-Disposition, possible values: +nil+ (default),
1054
<tt>:attachment</tt> and <tt>:inline</tt>
1057
Content-Length header, defaults to file size.
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.
1063
=== Accessing the Request Object
1065
The incoming request object can be accessed from request level (filter, routes,
1066
error handlers) through the <tt>request</tt> method:
1068
# app running on http://example.com/example
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"
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
1095
Some options, like <tt>script_name</tt> or <tt>path_info</tt>, can also be
1098
before { request.path_info = "/" }
1101
"all requests end up here"
1104
The <tt>request.body</tt> is an IO or StringIO object:
1107
request.body.rewind # in case someone already read it
1108
data = JSON.parse request.body.read
1109
"Hello #{data['name']}!"
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:
1122
You can also pass it a file name:
1125
attachment "info.txt"
1129
=== Looking Up Template Files
1131
The <tt>find_template</tt> helper is used to find template files for rendering:
1133
find_template settings.views, 'foo', Tilt[:haml] do |file|
1134
puts "could be #{file}"
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:
1141
set :views, ['views', 'templates']
1144
def find_template(views, name, engine, &block)
1145
Array(views).each { |v| super(v, name, engine, &block) }
1149
Another example would be using different directories for different engines:
1151
set :views, :sass => 'views/sass', :haml => 'templates', :default => 'views'
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)
1161
You can also easily wrap this up in an extension and share with others!
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
1172
Run once, at startup, in any environment:
1175
# setting one option
1176
set :option, 'value'
1178
# setting multiple options
1179
set :a => 1, :b => 2
1181
# same as `set :option, true`
1184
# same as `set :option, false`
1187
# you can also have dynamic settings with blocks
1188
set(:css_dir) { File.join(views, 'css') }
1191
Run only when the environment (RACK_ENV environment variable) is set to
1192
<tt>:production</tt>:
1194
configure :production do
1198
Run when the environment is set to either <tt>:production</tt> or
1201
configure :production, :test do
1205
You can access those options via <tt>settings</tt>:
1212
settings.foo? # => true
1213
settings.foo # => 'bar'
1217
=== Available Settings
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.
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.
1228
Disabled per default.
1230
[add_charsets] mime types the <tt>content_type</tt> helper will
1231
automatically add the charset info to.
1233
You should add to it rather than overriding this option:
1235
settings.add_charsets << "application/foobar"
1237
[app_file] main application file, used to detect project root,
1238
views and public folder and inline templates.
1240
[bind] IP address to bind to (default: 0.0.0.0).
1241
Only used for built-in server.
1243
[default_encoding] encoding to assume if unknown
1244
(defaults to <tt>"utf-8"</tt>).
1246
[dump_errors] display errors in the log.
1248
[environment] current environment, defaults to <tt>ENV['RACK_ENV']</tt>,
1249
or <tt>"development"</tt> if not available.
1251
[logging] use the logger.
1253
[lock] Places a lock around every request, only running
1254
processing on request per Ruby process concurrently.
1256
Enabled if your app is not thread-safe.
1257
Disabled per default.
1259
[method_override] use <tt>_method</tt> magic to allow put/delete forms in
1260
browsers that don't support it.
1262
[port] Port to listen on. Only used for built-in server.
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.
1269
[public] folder public files are served from
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).
1275
[root] project root folder.
1277
[raise_errors] raise exceptions (will stop application).
1279
[run] if enabled, Sinatra will handle starting the web server,
1280
do not enable if using rackup or other means.
1282
[running] is the built-in server running now?
1283
do not change this setting!
1285
[server] server or list of servers to use for built-in server.
1286
defaults to ['thin', 'mongrel', 'webrick'], order indicates
1289
[sessions] enable cookie based sessions.
1291
[show_exceptions] show a stack trace in the browser.
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.
1298
[views] views folder.
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.
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:
1312
'This is nowhere to be found.'
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:
1322
'Sorry there was a nasty error - ' + env['sinatra.error'].name
1327
error MyCustomError do
1328
'So what happened was...' + request.env['sinatra.error'].message
1331
Then, if this happens:
1334
raise MyCustomError, 'something bad'
1339
So what happened was... something bad
1341
Alternatively, you can install an error handler for a status code:
1357
Sinatra installs special <tt>not_found</tt> and <tt>error</tt> handlers when
1358
running under the development environment.
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.
1368
Sinatra makes building Rack middleware pipelines a cinch via a top-level
1372
require 'my_custom_middleware'
1375
use MyCustomMiddleware
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:
1386
use Rack::Auth::Basic do |username, password|
1387
username == 'admin' && password == 'secret'
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.
1397
Sinatra tests can be written using any Rack-based testing library
1398
or framework. {Rack::Test}[http://gitrdoc.com/brynary/rack-test] is
1401
require 'my_sinatra_app'
1405
class MyAppTest < Test::Unit::TestCase
1406
include Rack::Test::Methods
1409
Sinatra::Application
1414
assert_equal 'Hello World!', last_response.body
1417
def test_with_params
1418
get '/meet', :name => 'Frank'
1419
assert_equal 'Hello Frank!', last_response.body
1422
def test_with_rack_env
1423
get '/', {}, 'HTTP_USER_AGENT' => 'Songbird'
1424
assert_equal "You're using Songbird!", last_response.body
1428
NOTE: The built-in Sinatra::Test module and Sinatra::TestHarness class
1429
are deprecated as of the 0.9.2 release.
1431
== Sinatra::Base - Middleware, Libraries, and Modular Apps
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:
1441
require 'sinatra/base'
1443
class MyApp < Sinatra::Base
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:
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
1459
* Put your app's routes, error handlers, filters, and options in a subclass
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.
1466
=== Modular vs. Classic Style
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.
1471
There are only two downsides compared with modular style:
1473
* You may only have one Sinatra application per Ruby process. If you plan to
1474
use more, switch to modular style.
1476
* Classic style pollutes Object with delegator methods. If you plan to ship
1477
your application in a library/gem, switch to modular style.
1479
There is no reason you cannot mix modular and classic style.
1481
If switching from one style to the other, you should be aware of slight
1482
differences in the setting:
1484
Setting Classic Modular
1486
app_file file loading sinatra nil
1487
run $0 == app_file false
1489
method_override true false
1490
inline_templates true false
1493
=== Serving a Modular Application
1495
There are two common options for starting a modular app, actively starting with
1499
require 'sinatra/base'
1501
class MyApp < Sinatra::Base
1502
# ... app code here ...
1504
# start the server if ruby file executed directly
1505
run! if app_file == $0
1512
Or with a <tt>config.ru</tt>, which allows using any Rack handler:
1522
=== Using a Classic Style Application with a config.ru
1524
Write your app file:
1533
And a corresponding <tt>config.ru</tt>:
1536
run Sinatra::Application
1538
=== When to use a config.ru?
1540
Good signs you probably want to use a <tt>config.ru</tt>:
1542
* You want to deploy with a different Rack handler (Passenger, Unicorn,
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.
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>
1551
=== Using Sinatra as Middleware
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/...):
1558
require 'sinatra/base'
1560
class LoginScreen < Sinatra::Base
1563
get('/login') { haml :login }
1566
if params[:name] = 'admin' and params[:password] = 'admin'
1567
session['user_name'] = params[:name]
1574
class MyApp < Sinatra::Base
1575
# middleware will run before filters
1579
unless session['user_name']
1580
halt "Access denied, please <a href='/login'>login</a>."
1584
get('/') { "Hello #{session['user_name']}." }
1587
=== Dynamic Application Creation
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`:
1592
require 'sinatra/base'
1593
my_app = Sinatra.new { get('/') { "hi" } }
1596
It takes the application to inherit from as optional argument:
1598
require 'sinatra/base'
1600
controller = Sinatra.new do
1606
run Sinatra.new(controller) { get('/') { 'a' } }
1610
run Sinatra.new(controller) { get('/') { 'b' } }
1613
This is especially useful for testing Sinatra extensions or using Sinatra in
1616
This also makes using Sinatra as middleware extremely easy:
1618
require 'sinatra/base'
1624
run RailsProject::Application
1626
== Scopes and Binding
1628
The scope you are currently in determines what methods and variables are
1631
=== Application/Class Scope
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
1640
Options created via +set+ are methods at class level:
1642
class MyApp < Sinatra::Base
1643
# Hey, I'm in the application scope!
1648
# Hey, I'm no longer in the application scope!
1652
You have the application scope binding inside:
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>
1660
You can reach the scope object (the class) like this:
1662
* Via the object passed to configure blocks (<tt>configure { |c| ... }</tt>)
1663
* +settings+ from within request scope
1665
=== Request/Instance Scope
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:
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'
1679
settings.get("/#{params[:name]}") do
1680
# Request scope for "/#{params[:name]}"
1681
@value # => nil (not the same request)
1688
You have the request scope binding inside:
1690
* get/head/post/put/delete/options blocks
1691
* before/after filters
1695
=== Delegation Scope
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>.
1704
You have the delegate scope binding inside:
1706
* The top level binding, if you did <tt>require "sinatra"</tt>
1707
* An object extended with the <tt>Sinatra::Delegator</tt> mixin
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].
1715
Sinatra applications can be run directly:
1717
ruby myapp.rb [-h] [-x] [-e ENVIRONMENT] [-p PORT] [-o HOST] [-s HANDLER]
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)
1730
It is recommended to install Sinatra on Ruby 1.8.7, 1.9.2, JRuby or Rubinius.
1732
The following Ruby versions are officially supported:
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.
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.
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.
1753
Rubinius is officially supported (Rubinius >= 1.2.3), everything, including
1754
all template languages, works.
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.
1763
We also keep an eye on upcoming Ruby versions.
1765
The following Ruby implementations are not officially supported but still are
1766
known to run Sinatra:
1768
* Older versions of JRuby and Rubinius
1769
* MacRuby, Maglev, IronRuby
1770
* Ruby 1.9.0 and 1.9.1
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.
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
1779
Sinatra should work on any operating system supported by the chosen Ruby
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.
1786
We also push out prerelease gems from time to time, so you can do a
1788
gem install sinatra --pre
1790
To get some of the latest features.
1793
If you want to run your application with the latest Sinatra, using
1794
{Bundler}[http://gembundler.com/] is the recommended way.
1796
First, install bundler, if you haven't:
1800
Then, in your project directory, create a +Gemfile+:
1803
gem 'sinatra', :git => "git://github.com/sinatra/sinatra.git"
1805
# other dependencies
1806
gem 'haml' # for instance, if you use haml
1807
gem 'activerecord', '~> 3.0' # maybe you also need ActiveRecord 3.x
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.
1813
Now you can run your app like this:
1815
bundle exec ruby myapp.rb
1818
Create a local clone and run your app with the <tt>sinatra/lib</tt> directory
1819
on the <tt>$LOAD_PATH</tt>:
1822
git clone git://github.com/sinatra/sinatra.git
1823
ruby -Isinatra/lib myapp.rb
1825
To update the Sinatra sources in the future:
1830
=== Install Globally
1832
You can build the gem on your own:
1834
git clone git://github.com/sinatra/sinatra.git
1836
rake sinatra.gemspec
1839
If you install gems as root, the last step should be
1845
Sinatra follows {Semantic Versioning}[http://semver.org/], both SemVer and
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
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/