sinatra 1.2.0.d → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sinatra might be problematic. Click here for more details.

data/AUTHORS CHANGED
@@ -47,6 +47,8 @@ Sinatra would not be possible:
47
47
  translating whatever ends up in the README.
48
48
  * [Wordy](http://www.wordy.com/) for proofreading our README. 73e137d
49
49
  * cactus for digging through code and specs, multiple times.
50
+ * Nicolás Sanguinetti (foca) for strong demand of karma and shaping
51
+ helpers/register.
50
52
 
51
53
  and last but not least:
52
54
 
data/CHANGES CHANGED
@@ -1,4 +1,4 @@
1
- = 1.2.0 / Not Yet Released
1
+ = 1.2.0 / 2011-03-03
2
2
 
3
3
  * Added `slim` rendering method for rendering Slim templates. (Steve
4
4
  Hodgkiss)
@@ -47,7 +47,7 @@
47
47
  * Sinatra now ships with a Gemfile for development dependencies, since it eases
48
48
  supporting different platforms, like JRuby. (Konstantin Haase)
49
49
 
50
- = 1.1.3 / Not Yet Released
50
+ = 1.1.3 / 2011-02-20
51
51
 
52
52
  * Fixed issues with `user_agent` condition if the user agent header is missing.
53
53
  (Konstantin Haase)
@@ -838,6 +838,10 @@ Con cabeceras:
838
838
 
839
839
  halt 402, { 'Content-Type' => 'text/plain' }, 'venganza'
840
840
 
841
+ Obviamente, es posible utilizar +halt+ con una plantilla:
842
+
843
+ halt erb(:error)
844
+
841
845
  === Paso
842
846
 
843
847
  Una ruta puede pasarle el procesamiento a la siguiente ruta que coincida con
@@ -821,6 +821,10 @@ With headers:
821
821
 
822
822
  halt 402, {'Content-Type' => 'text/plain'}, 'revenge'
823
823
 
824
+ It is of course possible to combine a template with +halt+:
825
+
826
+ halt erb(:error)
827
+
824
828
  === Passing
825
829
 
826
830
  A route can punt processing to the next matching route using <tt>pass</tt>:
@@ -1,7 +1,9 @@
1
1
  = Sinatra
2
- <i>注:本文档仅仅是英文版的翻译,会出现内容没有及时更新的情况发生。如有不一致的地方,请以英文版为准。</i>
2
+ <i>注:本文档仅仅是英文版的翻译,会出现内容没有及时更新的情况发生。
3
+ 如有不一致的地方,请以英文版为准。</i>
3
4
 
4
- Sinatra是一个基于Ruby语言,以最小精力为代价快速创建web应用为目的的DSL(领域专属语言):
5
+ Sinatra是一个基于Ruby语言,以最小精力为代价快速创建web应用为目的的DSL
6
+ 领域专属语言):
5
7
 
6
8
  # myapp.rb
7
9
  require 'sinatra'
@@ -13,10 +15,12 @@ Sinatra是一个基于Ruby语言,以最小精力为代价快速创建web应用
13
15
  安装gem然后运行:
14
16
 
15
17
  gem install sinatra
16
- ruby rubygems myapp.rb
18
+ ruby -rubygems myapp.rb
17
19
 
18
20
  在该地址查看: http://localhost:4567
19
21
 
22
+ 推荐同时运行<tt>gem install thin</tt>,Sinatra会优先选择thin作为服务器。
23
+
20
24
  == 路由
21
25
 
22
26
  在Sinatra中,一个路由是一个HTTP方法与URL匹配范式的配对。
@@ -38,11 +42,14 @@ Sinatra是一个基于Ruby语言,以最小精力为代价快速创建web应用
38
42
  .. 消灭一些事物 ..
39
43
  end
40
44
 
45
+ options '/' do
46
+ .. 满足一些事物 ..
47
+ end
48
+
41
49
  路由按照它们被定义的顺序进行匹配。
42
50
  第一个与请求匹配的路由会被调用。
43
51
 
44
- 路由范式可以包括具名参数,
45
- 可通过<tt>params</tt>哈希表获得:
52
+ 路由范式可以包括具名参数,可通过<tt>params</tt>哈希表获得:
46
53
 
47
54
  get '/hello/:name' do
48
55
  # 匹配 "GET /hello/foo" 和 "GET /hello/bar"
@@ -121,7 +128,7 @@ Sinatra是一个基于Ruby语言,以最小精力为代价快速创建web应用
121
128
 
122
129
  === 返回值
123
130
 
124
- 一个路由代码块的返回值最少决定了返回给HTTP客户端的响应体,
131
+ 路由代码块的返回值至少决定了返回给HTTP客户端的响应体,
125
132
  或者至少决定了在Rack堆栈中的下一个中间件。
126
133
  大多数情况下,将是一个字符串,就像上面的例子中的一样。
127
134
  但是其他值也是可以接受的。
@@ -144,6 +151,47 @@ Rack body对象或者HTTP状态码:
144
151
 
145
152
  get('/') { Stream.new }
146
153
 
154
+ === 自定义路由匹配器
155
+
156
+ 如上显示,Sinatra内置了对于使用字符串和正则表达式作为路由匹配的支持。
157
+ 但是,它并没有只限于此。
158
+ 你可以非常容易地定义你自己的匹配器:
159
+
160
+ class AllButPattern
161
+ Match = Struct.new(:captures)
162
+
163
+ def initialize(except)
164
+ @except = except
165
+ @caputres = Match.new([])
166
+ end
167
+
168
+ def match(str)
169
+ @caputres unless @except === str
170
+ end
171
+ end
172
+
173
+ def all_but(pattern)
174
+ AllButPattern.new(pattern)
175
+ end
176
+
177
+ get all_but("/index") do
178
+ # ...
179
+ end
180
+
181
+ 请注意上面的例子可能超工程了,
182
+ 因为它也可以用更简单的方式表述:
183
+
184
+ get // do
185
+ pass if request.path_info == "/index"
186
+ # ...
187
+ end
188
+
189
+ 或者,使用消极向前查找:
190
+
191
+ get %r{^(?!/index$)} do
192
+ # ...
193
+ end
194
+
147
195
  == 静态文件
148
196
 
149
197
  静态文件是从 <tt>./public</tt> 目录提供服务。你可以通过设置<tt>:public</tt>
@@ -153,7 +201,7 @@ Rack body对象或者HTTP状态码:
153
201
 
154
202
  请注意public目录名并没有被包含在URL之中。文件
155
203
  <tt>./public/css/style.css</tt>是通过
156
- <tt>http://example.com/css/style.css</tt>地址访问。
204
+ <tt>http://example.com/css/style.css</tt>地址访问的。
157
205
 
158
206
  == 视图 / 模板
159
207
 
@@ -162,15 +210,15 @@ Rack body对象或者HTTP状态码:
162
210
 
163
211
  set :views, File.dirname(__FILE__) + '/templates'
164
212
 
165
- 请记住一件非常重要的事情,你只可以使用符号引用模板,
213
+ 请记住一件非常重要的事情,你只可以通过符号引用模板,
166
214
  即使它们在子目录下
167
215
  (在这种情况下,使用 <tt>:'subdir/template'</tt>)。
168
- 你必须使用一个符号,因为渲染方法会直接地渲染
169
- 任何传入的字符串。
216
+ 你必须使用一个符号,
217
+ 因为渲染方法会直接地渲染任何传入的字符串。
170
218
 
171
219
  === Haml模板
172
220
 
173
- 需要引入haml gem/library以渲染 HAML 模板:
221
+ 需要引入 <tt>haml</tt> gem/library以渲染 HAML 模板:
174
222
 
175
223
  # 你需要在你的应用中引入 haml
176
224
  require 'haml'
@@ -206,7 +254,7 @@ Rack body对象或者HTTP状态码:
206
254
 
207
255
  === Erubis
208
256
 
209
- 需要引入erubis gem/library以渲染 erubis 模板:
257
+ 需要引入 <tt>erubis</tt> gem/library以渲染 erubis 模板:
210
258
 
211
259
  # 你需要在你的应用中引入 erubis
212
260
  require 'erubis'
@@ -217,9 +265,20 @@ Rack body对象或者HTTP状态码:
217
265
 
218
266
  渲染 <tt>./views/index.erubis</tt>
219
267
 
268
+ 使用Erubis代替Erb也是可能的:
269
+
270
+ require 'erubis'
271
+ Tilt.register :erb, Tilt[:erubis]
272
+
273
+ get '/' do
274
+ erb :index
275
+ end
276
+
277
+ 使用Erubis来渲染 <tt>./views/index.erb</tt>。
278
+
220
279
  === Builder 模板
221
280
 
222
- 需要引入 builder gem/library 以渲染 builder templates:
281
+ 需要引入 <tt>builder</tt> gem/library 以渲染 builder templates:
223
282
 
224
283
  # 需要在你的应用中引入builder
225
284
  require 'builder'
@@ -232,7 +291,7 @@ Rack body对象或者HTTP状态码:
232
291
 
233
292
  === Nokogiri 模板
234
293
 
235
- 需要引入 nokogiri gem/library 以渲染 nokogiri 模板:
294
+ 需要引入 <tt>nokogiri</tt> gem/library 以渲染 nokogiri 模板:
236
295
 
237
296
  # 需要在你的应用中引入 nokogiri
238
297
  require 'nokogiri'
@@ -245,7 +304,7 @@ Rack body对象或者HTTP状态码:
245
304
 
246
305
  === Sass 模板
247
306
 
248
- 需要引入 haml gem/library 以渲染 Sass 模板:
307
+ 需要引入 <tt>haml</tt> 或者 <tt>sass</tt> gem/library 以渲染 Sass 模板:
249
308
 
250
309
  # 需要在你的应用中引入 haml 或者 sass
251
310
  require 'sass'
@@ -269,7 +328,7 @@ Rack body对象或者HTTP状态码:
269
328
 
270
329
  === Scss 模板
271
330
 
272
- 需要引入 haml gem/library 来渲染 Scss templates:
331
+ 需要引入 <tt>haml</tt> 或者 <tt>sass</tt> gem/library 来渲染 Scss templates:
273
332
 
274
333
  # 需要在你的应用中引入 haml 或者 sass
275
334
  require 'sass'
@@ -293,7 +352,7 @@ Rack body对象或者HTTP状态码:
293
352
 
294
353
  === Less 模板
295
354
 
296
- 需要引入 less gem/library 以渲染 Less 模板:
355
+ 需要引入 <tt>less</tt> gem/library 以渲染 Less 模板:
297
356
 
298
357
  # 需要在你的应用中引入 less
299
358
  require 'less'
@@ -306,7 +365,7 @@ Rack body对象或者HTTP状态码:
306
365
 
307
366
  === Liquid 模板
308
367
 
309
- 需要引入 liquid gem/library 来渲染 Liquid 模板:
368
+ 需要引入 <tt>liquid</tt> gem/library 来渲染 Liquid 模板:
310
369
 
311
370
  # 需要在你的应用中引入 liquid
312
371
  require 'liquid'
@@ -324,7 +383,7 @@ Rack body对象或者HTTP状态码:
324
383
 
325
384
  === Markdown 模板
326
385
 
327
- 需要引入 rdiscount gem/library 以渲染 Markdown 模板:
386
+ 需要引入 <tt>rdiscount</tt> gem/library 以渲染 Markdown 模板:
328
387
 
329
388
  # 需要在你的应用中引入rdiscount
330
389
  require "rdiscount"
@@ -336,7 +395,9 @@ Rack body对象或者HTTP状态码:
336
395
  渲染 <tt>./views/index.markdown</tt>
337
396
  (+md+ 和 +mkd+ 也是合理的文件扩展名)。
338
397
 
339
- 在markdown中是不可以调用方法的,也不可以传递 locals给它。你因此一般会结合其他的渲染引擎来使用它:
398
+ 在markdown中是不可以调用方法的,也不可以传递 locals给它。
399
+ 你因此一般会结合其他的渲染引擎来使用它:
400
+
340
401
 
341
402
  erb :overview, :locals => { :text => markdown(:introduction) }
342
403
 
@@ -345,9 +406,45 @@ Rack body对象或者HTTP状态码:
345
406
  %h1 Hello From Haml!
346
407
  %p= markdown(:greetings)
347
408
 
409
+ 既然你不能在Markdown中调用Ruby,你不能使用Markdown编写的布局。
410
+ 不过,使用其他渲染引擎作为模版的布局是可能的,
411
+ 通过传递<tt>:layout_engine</tt>选项:
412
+
413
+ get '/' do
414
+ markdown :index, :layout_engine => :erb
415
+ end
416
+
417
+ 这将会渲染 <tt>./views/index.md</tt> 并使用
418
+ <tt>./views/layout.erb</tt> 作为布局。
419
+
420
+ 请记住你可以全局设定这个选项:
421
+
422
+ set :markdown, :layout_engine => :haml, :layout => :post
423
+
424
+ get '/' do
425
+ markdown :index
426
+ end
427
+
428
+ 这将会渲染 <tt>./views/index.markdown</tt> (和任何其他的 Markdown
429
+ 模版) 并使用 <tt>./views/post.haml</tt> 作为布局.
430
+
431
+ 也可能使用BlueCloth而不是RDiscount来解析Markdown文件:
432
+
433
+ require 'bluecloth'
434
+
435
+ Tilt.register 'markdown', BlueClothTemplate
436
+ Tilt.register 'mkd', BlueClothTemplate
437
+ Tilt.register 'md', BlueClothTemplate
438
+
439
+ get '/' do
440
+ markdown :index
441
+ end
442
+
443
+ 使用BlueCloth来渲染 <tt>./views/index.md</tt> 。
444
+
348
445
  === Textile 模板
349
446
 
350
- 需要引入 RedCloth gem/library 以渲染 Textile 模板:
447
+ 需要引入 <tt>RedCloth</tt> gem/library 以渲染 Textile 模板:
351
448
 
352
449
  # 在你的应用中引入redcloth
353
450
  require "redcloth"
@@ -358,18 +455,41 @@ Rack body对象或者HTTP状态码:
358
455
 
359
456
  渲染 <tt>./views/index.textile</tt>。
360
457
 
361
- 在textile中是不可以调用方法的,也不可以传递 locals给它。你因此一般会结合其他的渲染引擎来使用它:
458
+ 在textile中是不可以调用方法的,也不可以传递 locals给它。
459
+ 你因此一般会结合其他的渲染引擎来使用它:
362
460
 
363
461
  erb :overview, :locals => { :text => textile(:introduction) }
364
462
 
365
- 请注意你也可以从其他模板中调用textile方法:
463
+ 请注意你也可以从其他模板中调用+textile+方法:
366
464
 
367
465
  %h1 Hello From Haml!
368
466
  %p= textile(:greetings)
369
467
 
468
+ 既然你不能在Textile中调用Ruby,你不能使用Textile编写的布局。
469
+ 不过,使用其他渲染引擎作为模版的布局是可能的,
470
+ 通过传递<tt>:layout_engine</tt>选项:
471
+
472
+ get '/' do
473
+ textile :index, :layout_engine => :erb
474
+ end
475
+
476
+ 这将会渲染 <tt>./views/index.textile</tt> 并使用
477
+ <tt>./views/layout.erb</tt> 作为布局。
478
+
479
+ 请记住你可以全局设定这个选项:
480
+
481
+ set :textile, :layout_engine => :haml, :layout => :post
482
+
483
+ get '/' do
484
+ textile :index
485
+ end
486
+
487
+ 这将会渲染 <tt>./views/index.textile</tt> (和任何其他的 Textile
488
+ 模版) 并使用 <tt>./views/post.haml</tt> 作为布局.
489
+
370
490
  === RDoc 模板
371
491
 
372
- 需要引入 RDoc gem/library 以渲染RDoc模板:
492
+ 需要引入 <tt>RDoc</tt> gem/library 以渲染RDoc模板:
373
493
 
374
494
  # 需要在你的应用中引入rdoc/markup/to_html
375
495
  require "rdoc/markup/to_html"
@@ -380,20 +500,43 @@ Rack body对象或者HTTP状态码:
380
500
 
381
501
  渲染 <tt>./views/index.rdoc</tt>。
382
502
 
383
- 在rdoc中是不可以调用方法的,也不可以传递 locals给它。你因此一般会结合其他的渲染引擎来使用它:
503
+ 在rdoc中是不可以调用方法的,也不可以传递locals给它。
504
+ 你因此一般会结合其他的渲染引擎来使用它:
384
505
 
385
506
  erb :overview, :locals => { :text => rdoc(:introduction) }
386
507
 
387
- 请注意你也可以从其他模板中调用rdoc方法:
508
+ 请注意你也可以从其他模板中调用+rdoc+方法:
388
509
 
389
510
  %h1 Hello From Haml!
390
511
  %p= rdoc(:greetings)
391
512
 
513
+ 既然你不能在RDoc中调用Ruby,你不能使用RDoc编写的布局。
514
+ 不过,使用其他渲染引擎作为模版的布局是可能的,
515
+ 通过传递<tt>:layout_engine</tt>选项:
516
+
517
+ get '/' do
518
+ rdoc :index, :layout_engine => :erb
519
+ end
520
+
521
+ 这将会渲染 <tt>./views/index.rdoc</tt> 并使用
522
+ <tt>./views/layout.erb</tt> 作为布局。
523
+
524
+ 请记住你可以全局设定这个选项:
525
+
526
+ set :rdoc, :layout_engine => :haml, :layout => :post
527
+
528
+ get '/' do
529
+ rdoc :index
530
+ end
531
+
532
+ 这将会渲染 <tt>./views/index.rdoc</tt> (和任何其他的 RDoc
533
+ 模版) 并使用 <tt>./views/post.haml</tt> 作为布局.
534
+
392
535
  === Radius 模板
393
536
 
394
- 需要引入 radius gem/library 以渲染 Radius 模板:
537
+ 需要引入 <tt>radius</tt> gem/library 以渲染 Radius 模板:
395
538
 
396
- # You'll need to require radius in your app
539
+ # 需要在你的应用中引入radius
397
540
  require 'radius'
398
541
 
399
542
  get '/' do
@@ -402,14 +545,14 @@ Rack body对象或者HTTP状态码:
402
545
 
403
546
  渲染 <tt>./views/index.radius</tt>。
404
547
 
405
- 因为你不能在Liquid 模板中调用 Ruby 方法 (除了 +yield+) ,
548
+ 因为你不能在Radius 模板中调用 Ruby 方法 (除了 +yield+) ,
406
549
  你几乎总是需要传递locals给它:
407
550
 
408
551
  radius :index, :locals => { :key => 'value' }
409
552
 
410
553
  === Markaby 模板
411
554
 
412
- 需要引入markaby gem/library以渲染Markaby模板:
555
+ 需要引入<tt>markaby</tt> gem/library以渲染Markaby模板:
413
556
 
414
557
  #需要在你的应用中引入 markaby
415
558
  require 'markaby'
@@ -420,9 +563,15 @@ Rack body对象或者HTTP状态码:
420
563
 
421
564
  渲染 <tt>./views/index.mab</tt>。
422
565
 
566
+ 你也可以使用嵌入的 Markaby:
567
+
568
+ get '/' do
569
+ markaby { h1 "Welcome!" }
570
+ end
571
+
423
572
  === Slim 模板
424
573
 
425
- 需要引入 slim gem/library 来渲染 Slim 模板:
574
+ 需要引入 <tt>slim</tt> gem/library 来渲染 Slim 模板:
426
575
 
427
576
  # 需要在你的应用中引入 slim
428
577
  require 'slim'
@@ -435,8 +584,16 @@ Rack body对象或者HTTP状态码:
435
584
 
436
585
  === CoffeeScript 模板
437
586
 
438
- 需要引入 coffee-script gem/library 并在路径中存在 `coffee` 二进制文件以渲染
439
- CoffeeScript 模板:
587
+ 需要引入 <tt>coffee-script</tt> gem/library 并至少满足下面条件一项
588
+ 以执行Javascript:
589
+
590
+ * +node+ (来自 Node.js) 在你的路径中
591
+ * 你正在运行 OSX
592
+ * +therubyracer+ gem/library
593
+
594
+ 请察看 http://github.com/josh/ruby-coffee-script 获取更新的选项。
595
+
596
+ 现在你可以渲染 CoffeeScript 模版了:
440
597
 
441
598
  # 需要在你的应用中引入coffee-script
442
599
  require 'coffee-script'
@@ -447,13 +604,13 @@ CoffeeScript 模板:
447
604
 
448
605
  渲染 <tt>./views/application.coffee</tt>。
449
606
 
450
- === 内联模板字符串
607
+ === 嵌入模板字符串
451
608
 
452
609
  get '/' do
453
610
  haml '%div.title Hello World'
454
611
  end
455
612
 
456
- 渲染内联模板字符串。
613
+ 渲染嵌入模板字符串。
457
614
 
458
615
  === 在模板中访问变量
459
616
 
@@ -472,7 +629,7 @@ CoffeeScript 模板:
472
629
  haml '%h1= foo.name', :locals => { :foo => foo }
473
630
  end
474
631
 
475
- 典型的使用情况是在别的模板中按照部分模板的方式来渲染。
632
+ 典型的使用情况是在别的模板中按照局部模板的方式来渲染。
476
633
 
477
634
 
478
635
  === 内联模板
@@ -515,27 +672,38 @@ CoffeeScript 模板:
515
672
  end
516
673
 
517
674
  如果存在名为"layout"的模板,该模板会在每个模板渲染的时候被使用。
518
- 你可以通过传送 <tt>:layout => false</tt>来禁用。
675
+ 你可以单独地通过传送 <tt>:layout => false</tt>来禁用,
676
+ 或者通过<tt>set :haml, :layout => false</tt>来禁用他们。
519
677
 
520
678
  get '/' do
521
679
  haml :index, :layout => !request.xhr?
522
680
  end
523
681
 
524
- == 辅助方法
682
+ === 关联文件扩展名
525
683
 
526
- 使用顶层的 <tt>helpers</tt> 方法来定义辅助方法,
527
- 以便在路由处理器和模板中使用:
684
+ 为了关联一个文件扩展名到一个模版引擎,使用
685
+ <tt>Tilt.register</tt>。比如,如果你喜欢使用
686
+ +tt+ 作为Textile模版的扩展名,你可以这样做:
687
+
688
+ Tilt.register :tt, Tilt[:textile]
689
+
690
+ === 添加你自己的模版引擎
691
+
692
+ 首先,通过Tilt注册你自己的引擎,然后创建一个渲染方法:
693
+
694
+ Tilt.register :myat, MyAwesomeTemplateEngine
528
695
 
529
696
  helpers do
530
- def bar(name)
531
- "#{name}bar"
532
- end
697
+ def myat(*args) render(:myat, *args) end
533
698
  end
534
699
 
535
- get '/:name' do
536
- bar(params[:name])
700
+ get '/' do
701
+ myat :index
537
702
  end
538
703
 
704
+ 渲染 <tt>./views/index.myat</tt>。察看 https://github.com/rtomayko/tilt
705
+ 来更多了解Tilt.
706
+
539
707
  == 过滤器
540
708
 
541
709
  前置过滤器在每个请求前,在请求的上下文环境中被执行,
@@ -560,6 +728,10 @@ CoffeeScript 模板:
560
728
  puts response.status
561
729
  end
562
730
 
731
+ 请注意:除非你显式使用 +body+ 方法,而不是在路由中直接返回字符串,
732
+ 消息体在后置过滤器是不可用的,
733
+ 因为它在之后才会生成。
734
+
563
735
  过滤器可以可选地带有范式,
564
736
  只有请求路径满足该范式时才会执行:
565
737
 
@@ -571,7 +743,63 @@ CoffeeScript 模板:
571
743
  session[:last_slug] = slug
572
744
  end
573
745
 
574
- == 挂起
746
+ 和路由一样,过滤器也可以带有条件:
747
+
748
+ before :agent => /Songbird/ do
749
+ # ...
750
+ end
751
+
752
+ after '/blog/*', :host_name => 'example.com' do
753
+ # ...
754
+ end
755
+
756
+ == 辅助方法
757
+
758
+ 使用顶层的 <tt>helpers</tt> 方法来定义辅助方法,
759
+ 以便在路由处理器和模板中使用:
760
+
761
+ helpers do
762
+ def bar(name)
763
+ "#{name}bar"
764
+ end
765
+ end
766
+
767
+ get '/:name' do
768
+ bar(params[:name])
769
+ end
770
+
771
+ === 使用 Sessions
772
+
773
+ Session被用来在请求之间保持状态。如果被激活,每一个用户会话
774
+ 对应有一个session哈希:
775
+
776
+ enable :sessions
777
+
778
+ get '/' do
779
+ "value = " << session[:value].inspect
780
+ end
781
+
782
+ get '/:value' do
783
+ session[:value] = params[:value]
784
+ end
785
+
786
+ 请注意 <tt>enable :sessions</tt> 实际上保存所有的数据在一个cookie之中。
787
+ 这可能不会总是做你想要的(比如,保存大量的数据会增加你的流量)。
788
+ 你可以使用任何的Rack session中间件,为了这么做,
789
+ *不要*调用 <tt>enable :sessions</tt>,而是
790
+ 按照自己的需要引入你的中间件:
791
+
792
+ use Rack::Session::Pool, :expire_after => 2592000
793
+
794
+ get '/' do
795
+ "value = " << session[:value].inspect
796
+ end
797
+
798
+ get '/:value' do
799
+ session[:value] = params[:value]
800
+ end
801
+
802
+ === 挂起
575
803
 
576
804
  要想直接地停止请求,在过滤器或者路由中使用:
577
805
 
@@ -593,7 +821,7 @@ CoffeeScript 模板:
593
821
 
594
822
  halt 402, {'Content-Type' => 'text/plain'}, 'revenge'
595
823
 
596
- == 让路
824
+ === 让路
597
825
 
598
826
  一个路由可以放弃处理,将处理让给下一个匹配的路由,使用 <tt>pass</tt>:
599
827
 
@@ -609,9 +837,222 @@ CoffeeScript 模板:
609
837
  路由代码块被直接退出,控制流继续前进到下一个匹配的路由。
610
838
  如果没有匹配的路由,将返回404。
611
839
 
612
- == 访问请求对象
840
+ === 触发另一个路由
841
+
842
+ 有些时候,+pass+ 并不是你想要的,你希望得到的是另一个路由的结果
843
+ 。简单的使用 +call+ 可以做到这一点:
844
+
845
+ get '/foo' do
846
+ status, headers, body = call request.env.merge("PATH_INFO" => '/bar')
847
+ [status, body.upcase]
848
+ end
849
+
850
+ get '/bar' do
851
+ "bar"
852
+ end
853
+
854
+ 请注意在以上例子中,你可以更加简化测试并增加性能,只要简单的移动
855
+ <tt>"bar"</tt>到一个被<tt>/foo</tt>
856
+ 和 <tt>/bar</tt>同时使用的helper。
857
+
858
+ 如果你希望请求被发送到同一个应用,而不是副本,
859
+ 使用 <tt>call!</tt> 而不是 <tt>call</tt>.
860
+
861
+ 察看 Rack specification 如果你想更多了解 <tt>call</tt>.
862
+
863
+ === 设定 消息体,状态码和消息头
864
+
865
+ 通过路由代码块的返回值来设定状态码和消息体不仅是可能的,而且是推荐的。
866
+ 但是,在某些场景中你可能想在作业流程中的特定点上设置消息体。
867
+ 你可以通过 +body+ 辅助方法这么做。
868
+ 如果你这样做了,
869
+ 你可以在那以后使用该方法获得消息体:
870
+
871
+ get '/foo' do
872
+ body "bar"
873
+ end
874
+
875
+ after do
876
+ puts body
877
+ end
878
+
879
+ 也可以传一个代码块给 +body+,它将会被Rack处理器执行(
880
+ 这将可以被用来实现streaming,参见“返回值”)。
881
+
882
+ 和消息体类似,你也可以设定状态码和消息头:
883
+
884
+ get '/foo' do
885
+ status 418
886
+ headers \
887
+ "Allow" => "BREW, POST, GET, PROPFIND, WHEN"
888
+ "Refresh" => "Refresh: 20; http://www.ietf.org/rfc/rfc2324.txt"
889
+ body "I'm a tea pot!"
890
+ end
891
+
892
+ 如同 +body+, 不带参数的 +headers+ 和 +status+ 可以用来访问
893
+ 他们你的当前值.
894
+
895
+ === 媒体类型
896
+
897
+ 当使用 <tt>send_file</tt> 或者静态文件的场合,你的媒体类型可能
898
+ Sinatra并不理解。使用 +mime_type+ 通过文件扩展名来注册它们:
899
+
900
+ mime_type :foo, 'text/foo'
901
+
902
+ 你也可以通过 +content_type+ 辅助方法使用:
903
+
904
+ get '/' do
905
+ content_type :foo
906
+ "foo foo foo"
907
+ end
908
+
909
+ === 生成 URL
910
+
911
+ 为了生成URL,你需要使用 +url+ 辅助方法,
912
+ 例如,在Haml中:
913
+
914
+ %a{:href => url('/foo')} foo
915
+
916
+ 它会根据反向代理和Rack路由,如果有的话,来计算生成的URL。
917
+
918
+ 这个方法还有一个别名 +to+ (见下面的例子).
919
+
920
+ === 浏览器重定向
921
+
922
+ 你可以通过 +redirect+ 辅助方法触发浏览器重定向:
923
+
924
+ get '/foo' do
925
+ redirect to('/bar')
926
+ end
927
+
928
+ 任何额外的参数都会被以 +halt+相同的方式来处理:
929
+
930
+ redirect to('/bar'), 303
931
+ redirect 'http://google.com', 'wrong place, buddy'
932
+
933
+ 你可以方便的通过
934
+ <tt>redirect back</tt>把用户重定向到来自的页面:
935
+
936
+ get '/foo' do
937
+ "<a href='/bar'>do something</a>"
938
+ end
939
+
940
+ get '/bar' do
941
+ do_something
942
+ redirect back
943
+ end
944
+
945
+ 为了传递参数给redirect,或者加入query:
946
+
947
+ redirect to('/bar?sum=42')
948
+
949
+ 或者使用session:
950
+
951
+ enable :session
952
+
953
+ get '/foo' do
954
+ session[:secret] = 'foo'
955
+ redirect to('/bar')
956
+ end
957
+
958
+ get '/bar' do
959
+ session[:secret]
960
+ end
961
+
962
+ === 缓存控制
963
+
964
+ 正确地设定消息头是恰当的HTTP缓存的基础。
613
965
 
614
- 传入的请求对象可以在请求层(过滤器,路由,错误处理)通过 `request` 方法被访问:
966
+ 你可以方便的设定 Cache-Control 消息头,像这样:
967
+
968
+ get '/' do
969
+ cache_control :public
970
+ "cache it!"
971
+ end
972
+
973
+ 核心提示: 在前置过滤器中设定缓存.
974
+
975
+ before do
976
+ cache_control :public, :must_revalidate, :max_age => 60
977
+ end
978
+
979
+ 如果你正在用 +expires+ 辅助方法设定对应的消息头
980
+ <tt>Cache-Control</tt> 会自动设定:
981
+
982
+ before do
983
+ expires 500, :public, :must_revalidate
984
+ end
985
+
986
+ 为了合适地使用缓存,你应该考虑使用 +etag+ 和 +last_modified+方法。.
987
+ 推荐在执行繁重任务*之前*使用这些helpers,
988
+ 他们会立刻发送响应,如果客户端在缓存中已经有了当前版本。
989
+
990
+ get '/article/:id' do
991
+ @article = Article.find params[:id]
992
+ last_modified @article.updated_at
993
+ etag @article.sha1
994
+ erb :article
995
+ end
996
+
997
+ 使用
998
+ {weak ETag}[http://en.wikipedia.org/wiki/HTTP_ETag#Strong_and_weak_validation]
999
+ 也是有可能的:
1000
+
1001
+ etag @article.sha1, :weak
1002
+
1003
+ 这些辅助方法并不会为你做任何缓存,而是将必要的信息传送给你的缓存
1004
+ 如果你在寻找缓存的快速解决方案,试试
1005
+ {rack-cache}[http://rtomayko.github.com/rack-cache/]:
1006
+
1007
+ require "rack/cache"
1008
+ require "sinatra"
1009
+
1010
+ use Rack::Cache
1011
+
1012
+ get '/' do
1013
+ cache_control :public, :max_age => 36000
1014
+ sleep 5
1015
+ "hello"
1016
+ end
1017
+
1018
+ === 发送文件
1019
+
1020
+ 为了发送文件,你可以使用 <tt>send_file</tt> 辅助方法:
1021
+
1022
+ get '/' do
1023
+ send_file 'foo.png'
1024
+ end
1025
+
1026
+ 也可以带一些选项:
1027
+
1028
+ send_file 'foo.png', :type => :jpg
1029
+
1030
+ 可用的选项有:
1031
+
1032
+ [filename]
1033
+ 响应中的文件名,默认是真实文件的名字。
1034
+
1035
+ [last_modified]
1036
+ Last-Modified 消息头的值,默认是文件的mtime(修改时间)。
1037
+
1038
+ [type]
1039
+ 使用的内容类型,如果没有会从文件扩展名猜测。
1040
+
1041
+ [disposition]
1042
+ 用于 Content-Disposition,可能的包括: +nil+ (默认),
1043
+ <tt>:attachment</tt> 和 <tt>:inline</tt>
1044
+
1045
+ [length]
1046
+ Content-Length 的值,默认是文件的大小。
1047
+
1048
+ 如果Rack处理器支持,Ruby进程除streaming以外的方式会被使用。
1049
+ 如果你使用这个辅助方法,
1050
+ Sinatra会自动处理range请求。
1051
+
1052
+ === 访问请求对象
1053
+
1054
+ 传入的请求对象可以在请求层(过滤器,路由,错误处理)
1055
+ 通过 <tt>request</tt> 方法被访问:
615
1056
 
616
1057
  # 在 http://example.com/example 上运行的应用
617
1058
  get '/foo' do
@@ -628,14 +1069,15 @@ CoffeeScript 模板:
628
1069
  request.get? # true (其他动词也具有类似方法)
629
1070
  request.form_data? # false
630
1071
  request["SOME_HEADER"] # SOME_HEADER header的值
631
- request.referer # 客户端的referer 或者 '/'
1072
+ request.referrer # 客户端的referrer 或者 '/'
632
1073
  request.user_agent # user agent (被 :agent 条件使用)
633
1074
  request.cookies # 浏览器 cookies 哈希
634
1075
  request.xhr? # 这是否是ajax请求?
635
1076
  request.url # "http://example.com/example/foo"
636
1077
  request.path # "/example/foo"
637
1078
  request.ip # 客户端IP地址
638
- request.secure? # false
1079
+ request.secure? # false(如果是ssl则为true)
1080
+ request.forwarded? # true (如果是运行在反向代理之后)
639
1081
  request.env # Rack中使用的未处理的env哈希
640
1082
  end
641
1083
 
@@ -656,12 +1098,83 @@ CoffeeScript 模板:
656
1098
  "Hello #{data['name']}!"
657
1099
  end
658
1100
 
1101
+ === 附件
1102
+
1103
+ 你可以使用 +attachment+ 辅助方法来告诉浏览器响应
1104
+ 应当被写入磁盘而不是在浏览器中显示。
1105
+
1106
+ get '/' do
1107
+ attachment
1108
+ "store it!"
1109
+ end
1110
+
1111
+ 你也可以传递一个文件名:
1112
+
1113
+ get '/' do
1114
+ attachment "info.txt"
1115
+ "store it!"
1116
+ end
1117
+
1118
+ === 查找模板文件
1119
+
1120
+ <tt>find_template</tt> 辅助方法被用于在渲染时查找模板文件:
1121
+
1122
+ find_template settings.views, 'foo', Tilt[:haml] do |file|
1123
+ puts "could be #{file}"
1124
+ end
1125
+
1126
+ 这并不是很有用。但是在你需要重载这个方法
1127
+ 来实现你自己的查找机制的时候有用。
1128
+ 比如,如果你想支持多于一个视图目录:
1129
+
1130
+ set :views, ['views', 'templates']
1131
+
1132
+ helpers do
1133
+ def find_template(views, name, engine, &block)
1134
+ Array(views).each { |v| super(v, name, engine, &block) }
1135
+ end
1136
+ end
1137
+
1138
+ 另一个例子是为不同的引擎使用不同的目录:
1139
+
1140
+ set :views, :sass => 'views/sass', :haml => 'templates', :default => 'views'
1141
+
1142
+ helpers do
1143
+ def find_template(views, name, engine, &block)
1144
+ _, folder = views.detect { |k,v| engine == Tilt[k] }
1145
+ folder ||= views[:default]
1146
+ super(folder, name, engine, &block)
1147
+ end
1148
+ end
1149
+
1150
+ 你可以很容易地包装成一个扩展然后与他人分享!
1151
+
1152
+ 请注意 <tt>find_template</tt> 并不会检查文件真的存在,
1153
+ 而是对任何可能的路径调用给入的代码块。这并不会带来性能问题,
1154
+ 因为 +render+ 会在找到文件的时候马上使用 +break+ 。
1155
+ 同样的,模板的路径(和内容)会在除development mode以外的场合
1156
+ 被缓存。你应该时刻提醒自己这一点,
1157
+ 如果你真的想写一个非常疯狂的方法。
1158
+
659
1159
  == 配置
660
1160
 
661
1161
  运行一次,在启动的时候,在任何环境下:
662
1162
 
663
1163
  configure do
664
- ...
1164
+ # setting one option
1165
+ set :option, 'value'
1166
+
1167
+ # setting multiple options
1168
+ set :a => 1, :b => 2
1169
+
1170
+ # same as `set :option, true`
1171
+ enable :option
1172
+
1173
+ # same as `set :option, false`
1174
+ disable :option
1175
+
1176
+ # you can also have dynamic settings with blocks
1177
+ set(:css_dir) { File.join(views, 'css') }
665
1178
  end
666
1179
 
667
1180
  只当环境 (RACK_ENV environment 变量) 被设定为
@@ -678,6 +1191,101 @@ CoffeeScript 模板:
678
1191
  ...
679
1192
  end
680
1193
 
1194
+ 你可以使用 <tt>settings</tt> 获得这些配置:
1195
+
1196
+ configure do
1197
+ set :foo, 'bar'
1198
+ end
1199
+
1200
+ get '/' do
1201
+ settings.foo? # => true
1202
+ settings.foo # => 'bar'
1203
+ ...
1204
+ end
1205
+
1206
+ === 可选的设置
1207
+
1208
+ [absolute_redirects] 如果被禁用,Sinatra会允许使用相对路径重定向,
1209
+ 但是,Sinatra就不再遵守 RFC 2616标准
1210
+ (HTTP 1.1), 该标准只允许绝对路径重定向。
1211
+
1212
+ 如果你的应用运行在一个未恰当设置的反向代理之后,
1213
+ 你需要启用这个选项。注意 +url+ 辅助方法
1214
+ 仍然会生成绝对 URL,除非你传入
1215
+ +false+ 作为第二参数。
1216
+
1217
+ 默认禁用。
1218
+
1219
+ [add_charsets] 设定 <tt>content_type</tt> 辅助方法会
1220
+ 自动加上字符集信息的多媒体类型。
1221
+
1222
+ 你应该添加而不是覆盖这个选项:
1223
+
1224
+ settings.add_charsets << "application/foobar"
1225
+
1226
+ [app_file] 主应用文件,用来检测项目的根路径,
1227
+ views和public文件夹和内联模板。
1228
+
1229
+ [bind] 绑定的IP 地址 (默认: 0.0.0.0)。
1230
+ 仅对于内置的服务器有用。
1231
+
1232
+ [default_encoding] 默认编码
1233
+ (默认为 <tt>"utf-8"</tt>)。
1234
+
1235
+ [dump_errors] 在log中显示错误。
1236
+
1237
+ [environment] 当前环境,默认是 <tt>ENV['RACK_ENV']</tt>,
1238
+ 或者 <tt>"development"</tt> 如果不可用。
1239
+
1240
+ [logging] 使用logger
1241
+
1242
+ [lock] 对每一个请求放置一个锁,
1243
+ 只使用进程并发处理请求。
1244
+
1245
+ 如果你的应用不是线程安全则需启动。
1246
+ 默认禁用。
1247
+
1248
+ [method_override] 使用 <tt>_method</tt> 魔法以允许在旧的浏览器中在
1249
+ 表单中使用 put/delete 方法
1250
+
1251
+ [port] 监听的端口号。只对内置服务器有用。
1252
+
1253
+ [prefixed_redirects] 是否添加 <tt>request.script_name</tt> 到
1254
+ 重定向请求,如果没有设定绝对路径。那样的话
1255
+ <tt>redirect '/foo'</tt> 会和
1256
+ <tt>redirect to('/foo')</tt>起相同作用。默认禁用。
1257
+
1258
+ [public] public文件夹的位置。
1259
+
1260
+ [reload_templates] 是否每个请求都重新载入模板。
1261
+ 在development mode和 Ruby 1.8.6 中被企业(用来
1262
+ 消除一个Ruby内存泄漏的bug)。
1263
+
1264
+ [root] 项目的根目录。
1265
+
1266
+ [raise_errors] 抛出异常(应用会停下)。
1267
+
1268
+ [run] 如果启用,Sinatra会开启web服务器。
1269
+ 如果使用rackup或其他方式则不要启用。
1270
+
1271
+ [running] 内置的服务器在运行吗?
1272
+ 不要修改这个设置!
1273
+
1274
+ [server] 服务器,或用于内置服务器的列表。
1275
+ 默认是 ['thin', 'mongrel', 'webrick'], 顺序表明了
1276
+ 优先级。
1277
+
1278
+ [sessions] 开启基于cookie的sesson。
1279
+
1280
+ [show_exceptions] 在浏览器中显示一个stack trace。
1281
+
1282
+ [static] Sinatra是否处理静态文件。
1283
+ 当服务器能够处理则禁用。
1284
+ 禁用会增强性能。
1285
+ 默认开启。
1286
+
1287
+ [views] views 文件夹。
1288
+
681
1289
  == 错误处理
682
1290
 
683
1291
  错误处理在与路由和前置过滤器相同的上下文中运行,
@@ -738,17 +1346,6 @@ CoffeeScript 模板:
738
1346
  在运行在development环境下时,Sinatra会安装特殊的
739
1347
  <tt>not_found</tt> 和 <tt>error</tt> 处理器。
740
1348
 
741
- == 媒体类型
742
-
743
- 当使用 <tt>send_file</tt> 或者静态文件的适合,你的媒体类型可能
744
- Sinatra并不理解。使用 +mime_type+ 通过文件扩展名来注册它们:
745
-
746
- mime_type :foo, 'text/foo'
747
-
748
- 你也可以通过 +content_type+ 辅助方法使用:
749
-
750
- content_type :foo
751
-
752
1349
  == Rack 中间件
753
1350
 
754
1351
  Sinatra 依靠 Rack[http://rack.rubyforge.org/],
@@ -770,10 +1367,9 @@ Sinatra 让建立Rack中间件管道异常简单,
770
1367
  'Hello World'
771
1368
  end
772
1369
 
773
- +use+ 的语义和在Rack::Builder[http://rack.rubyforge.org/doc/classes/Rack/Builder.html] DSL
774
- (在rack文件中最频繁使用)
775
- 中定义的完全一样。例如,+use+ 方法
776
- 接受 多个/可变 参数,包括代码块:
1370
+ +use+ 的语义和在 Rack::Builder[http://rack.rubyforge.org/doc/classes/Rack/Builder.html]
1371
+ DSL(在rack文件中最频繁使用)中定义的完全一样。例如,+use+
1372
+ 方法接受 多个/可变 参数,包括代码块:
777
1373
 
778
1374
  use Rack::Auth::Basic do |username, password|
779
1375
  username == 'admin' && password == 'secret'
@@ -822,11 +1418,11 @@ Sinatra的测试可以使用任何基于Rack的测试程序库或者框架来编
822
1418
 
823
1419
  == Sinatra::Base - 中间件,程序库和模块化应用
824
1420
 
825
- 把你的应用定义在顶层,对于微型应用这会工作得很好,但是在
826
- 构建可复用的组件时候会带来客观的不利,
1421
+ 把你的应用定义在顶层,对于微型应用这会工作得很好,
1422
+ 但是在构建可复用的组件时候会带来客观的不利,
827
1423
  比如构建Rack中间件,Rails metal,带有服务器组件的简单程序库,
828
- 或者甚至是Sinatra扩展。顶层的DSL污染了Object命名空间并
829
- 假定了一个微型应用风格的配置 (例如, 单一的应用文件,
1424
+ 或者甚至是Sinatra扩展。顶层的DSL污染了Object命名空间,
1425
+ 并假定了一个微型应用风格的配置 (例如, 单一的应用文件,
830
1426
  ./public 和 ./views 目录,日志,异常细节页面,等等)。
831
1427
  这时应该让 Sinatra::Base 走到台前了:
832
1428
 
@@ -841,16 +1437,9 @@ Sinatra的测试可以使用任何基于Rack的测试程序库或者框架来编
841
1437
  end
842
1438
  end
843
1439
 
844
- MyApp 类是一个独立的Rack组件,可以扮演
845
- Rack中间件,一个Rack应用,或者 Rails metal。你可以从rackup +config.ru文件
846
- +use+ 或者 +run+ 这个类;或者,
847
- 直接控制作为程序库提供的服务器组件:
848
-
849
- MyApp.run! :host => 'localhost', :port => 9090
850
-
851
- Sinatra::Base子类可用的方法实际上就是
852
- 通过顶层DSL可用的方法。大部分顶层应用可以通过两个改变
853
- 转换成Sinatra::Base组件:
1440
+ Sinatra::Base子类可用的方法实际上就是通过顶层 DSL
1441
+ 可用的方法。
1442
+ 大部分顶层应用可以通过两个改变转换成Sinatra::Base组件:
854
1443
 
855
1444
  * 你的文件应当引入 +sinatra/base+ 而不是 +sinatra+;
856
1445
  否则,所有的Sinatra的 DSL 方法将会被引进到
@@ -862,10 +1451,95 @@ Sinatra::Base子类可用的方法实际上就是
862
1451
  包含内置的服务器。参见 {选项和配置}[http://sinatra.github.com/configuration.html]
863
1452
  查看可用选项的具体细节和他们的行为。
864
1453
 
1454
+ === 模块化 vs. 传统的方式
1455
+
1456
+ 与通常的认识相反,传统的方式没有任何错误。
1457
+ 如果它适合你的应用,你不需要转换到模块化的应用。
1458
+
1459
+ 和模块化方式相比只有两个缺点:
1460
+
1461
+ * 你对每个Ruby进程只能定义一个Sinatra应用,如果你需要更多,
1462
+ 切换到模块化方式。
1463
+
1464
+ * 传统方式使用代理方法污染了 Object 。如果你打算
1465
+ 把你的应用封装进一个 library/gem,转换到模块化方式。
1466
+
1467
+ 没有任何原因阻止你混合模块化和传统方式。
1468
+
1469
+ 如果从一种转换到另一种,你需要注意settings中的
1470
+ 一些微小的不同:
1471
+
1472
+ Setting Classic Modular
1473
+
1474
+ app_file file loading sinatra nil
1475
+ run $0 == app_file false
1476
+ logging true false
1477
+ method_override true false
1478
+ inline_templates true false
1479
+
1480
+
1481
+ === 运行一个模块化应用
1482
+
1483
+ 有两种方式运行一个模块化应用,使用
1484
+ <tt>run!</tt>来运行:
1485
+
1486
+ # my_app.rb
1487
+ require 'sinatra/base'
1488
+
1489
+ class MyApp < Sinatra::Base
1490
+ # ... app code here ...
1491
+
1492
+ # start the server if ruby file executed directly
1493
+ run! if app_file == $0
1494
+ end
1495
+
1496
+ 运行:
1497
+
1498
+ ruby my_app.rb
1499
+
1500
+ 或者使用一个 <tt>config.ru</tt>,允许你使用任何Rack处理器:
1501
+
1502
+ # config.ru
1503
+ require 'my_app'
1504
+ run MyApp
1505
+
1506
+ 运行:
1507
+
1508
+ rackup -p 4567
1509
+
1510
+ === 使用config.ru运行传统方式的应用
1511
+
1512
+ 编写你的应用:
1513
+
1514
+ # app.rb
1515
+ require 'sinatra'
1516
+
1517
+ get '/' do
1518
+ 'Hello world!'
1519
+ end
1520
+
1521
+ 加入相应的 <tt>config.ru</tt>:
1522
+
1523
+ require 'app'
1524
+ run Sinatra::Application
1525
+
1526
+ === 什么时候用 config.ru?
1527
+
1528
+ 以下情况你可能需要使用 <tt>config.ru</tt>:
1529
+
1530
+ * 你要使用不同的 Rack 处理器部署 (Passenger, Unicorn,
1531
+ Heroku, ...).
1532
+ * 你想使用一个或者多个 <tt>Sinatra::Base</tt>的子类.
1533
+ * 你只想把Sinatra当作中间件使用,而不是端点。
1534
+
1535
+ <b>你并不需要切换到<tt>config.ru</tt>仅仅因为你切换到模块化方式,
1536
+ 你同样不需要切换到模块化方式,
1537
+ 仅仅因为要运行 <tt>config.ru</tt>.</b>
1538
+
865
1539
  === 把Sinatra当成中间件来使用
866
1540
 
867
1541
  不仅Sinatra有能力使用其他的Rack中间件,任何Sinatra
868
- 应用程序都可以反过来自身被当作中间件,被加在任何Rack断电前面。
1542
+ 应用程序都可以反过来自身被当作中间件,被加在任何Rack端点前面。
869
1543
  这个端点可以是任何Sinatra应用,或者任何基于Rack的应用程序
870
1544
  (Rails/Ramaze/Camping/...)。
871
1545
 
@@ -997,34 +1671,125 @@ Sinatra 应用可以被直接运行:
997
1671
  -o # 设定主机名 (默认是 0.0.0.0)
998
1672
  -e # 设定环境 (默认是 development)
999
1673
  -s # 限定 rack 服务器/处理器 (默认是 thin)
1000
- -x # 打开互斥标记锁 (默认是 off)
1674
+ -x # 打开互斥锁 (默认是 off)
1675
+
1676
+ == 必要条件
1677
+
1678
+ 推荐在 Ruby 1.8.7, 1.9.2, JRuby 或者 Rubinius 上安装Sinatra。
1679
+
1680
+ 下面的Ruby版本是官方支持的:
1681
+
1682
+ [ Ruby 1.8.6 ]
1683
+ 不推荐在1.8.6上安装Sinatra,
1684
+ 但是直到Sinatra 1.3.0发布才会放弃对它的支持。
1685
+ RDoc 和 CoffeScript模板不被这个Ruby版本支持。
1686
+ 1.8.6在它的Hash实现中包含一个内存泄漏问题,
1687
+ 该问题会被1.1.1版本之前的Sinatra引发。
1688
+ 当前版本使用性能下降的代价排除了这个问题。你需要把Rack降级到1.1.x,
1689
+ 因为Rack >= 1.2不再支持1.8.6。
1690
+
1691
+ [ Ruby 1.8.7 ]
1692
+ 1.8.7 被完全支持,但是,如果没有特别原因,
1693
+ 我们推荐你升级到 1.9.2 或者切换到 JRuby 或者 Rubinius.
1694
+
1695
+ [ Ruby 1.9.2 ]
1696
+ 1.9.2 被支持而且推荐。注意 Radius 和 Markaby
1697
+ 模板并不和1.9兼容。不要使用 1.9.2p0, 它被已知会产生
1698
+ segmentation faults.
1699
+
1700
+ [ Rubinius ]
1701
+ Rubinius 被官方支持 (Rubinius >= 1.2.2),
1702
+ 除了Textile模板。
1703
+
1704
+ [ JRuby ]
1705
+ JRuby 被官方支持 (JRuby >= 1.5.6)。
1706
+ 目前未知和第三方模板库有关的问题,
1707
+ 但是,如果你选择了JRuby,请查看一下JRuby rack 处理器,
1708
+ 因为 Thin web 服务器还没有在JRuby上获得支持。
1709
+
1710
+ 我们也会时刻关注新的Ruby版本。
1711
+
1712
+ 下面的 Ruby 实现没有被官方支持,
1713
+ 但是已知可以运行 Sinatra:
1714
+
1715
+ * JRuby 和 Rubinius 老版本
1716
+ * MacRuby
1717
+ * Maglev
1718
+ * IronRuby
1719
+ * Ruby 1.9.0 and 1.9.1
1720
+
1721
+ 不被官方支持的意思是,如果在不被支持的平台上有运行错误,
1722
+ 我们假定不是我们的问题,而是平台的问题。
1723
+
1724
+ Sinatra应该会运行在任何支持上述Ruby实现的操作系统。
1001
1725
 
1002
- == 紧追前沿
1003
1726
 
1004
- 如果你喜欢使用 Sinatra 的最新鲜的代码,创建一个本地克隆
1005
- , 把<tt>sinatra/lib</tt> 目录添加到
1006
- <tt>LOAD_PATH</tt>后运行你的应用:
1727
+ == 紧追前沿
1007
1728
 
1729
+ 如果你喜欢使用 Sinatra 的最新鲜的代码,请放心的使用 master
1730
+ 分支来运行你的程序,它会非常的稳定。
1008
1731
  cd myapp
1009
1732
  git clone git://github.com/sinatra/sinatra.git
1010
1733
  ruby -Isinatra/lib myapp.rb
1011
1734
 
1012
- 另一种方法是,你也可以在你的应用中,添加 <tt>sinatra/lib</tt> 目录到
1013
- <tt>LOAD_PATH</tt>:
1735
+ 我们也会不定期的发布预发布gems,所以你也可以运行
1014
1736
 
1015
- $LOAD_PATH.unshift File.dirname(__FILE__) + '/sinatra/lib'
1016
- require 'rubygems'
1017
- require 'sinatra'
1737
+ gem install sinatra --pre
1018
1738
 
1019
- get '/about' do
1020
- "I'm running version " + Sinatra::VERSION
1021
- end
1739
+ 来获得最新的特性。
1740
+
1741
+ === 通过Bundler
1742
+ 如果你想使用最新的Sinatra运行你的应用,通过
1743
+ {Bundler}[http://gembundler.com/] 是推荐的方式。
1744
+
1745
+ 首先,安装bundler,如果你还没有安装:
1746
+
1747
+ gem install bundler
1748
+
1749
+ 然后,在你的项目目录下,创建一个 +Gemfile+:
1750
+
1751
+ source :rubygems
1752
+ gem 'sinatra', :git => "git://github.com/sinatra/sinatra.git"
1753
+
1754
+ # 其他的依赖关系
1755
+ gem 'haml' # 举例,如果你想用haml
1756
+ gem 'activerecord', '~> 3.0' # 也许你还需要 ActiveRecord 3.x
1757
+
1758
+ 请注意在这里你需要列出你的应用的所有依赖关系。
1759
+ Sinatra的直接依赖关系 (Rack and Tilt) 将会,
1760
+ 自动被Bundler获取和添加。
1761
+
1762
+ 现在你可以像这样运行你的应用:
1763
+
1764
+ bundle exec ruby myapp.rb
1022
1765
 
1023
- 在未来,要更新Sinatra源代码:
1766
+ === 使用自己的
1767
+ 创建一个本地克隆并通过 <tt>sinatra/lib</tt> 目录运行你的应用,
1768
+ 通过 <tt>$LOAD_PATH</tt>:
1024
1769
 
1025
- cd myproject/sinatra
1770
+ cd myapp
1771
+ git clone git://github.com/sinatra/sinatra.git
1772
+ ruby -Isinatra/lib myapp.rb
1773
+
1774
+ 为了在未来更新 Sinatra 源代码:
1775
+
1776
+ cd myapp/sinatra
1026
1777
  git pull
1027
1778
 
1779
+ === 全局安装
1780
+
1781
+ 你可以自行编译 gem :
1782
+
1783
+
1784
+ git clone git://github.com/sinatra/sinatra.git
1785
+ cd sinatra
1786
+ rake sinatra.gemspec
1787
+ rake install
1788
+
1789
+ 如果你以root身份安装 gems,最后一步应该是
1790
+
1791
+ sudo rake install
1792
+
1028
1793
  == 更多
1029
1794
 
1030
1795
  * {项目主页(英文)}[http://www.sinatrarb.com/] - 更多的文档,