devcenter 0.0.3 → 0.0.4

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