sinatra-base 1.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. data/.yardopts +4 -0
  2. data/AUTHORS +15 -0
  3. data/CHANGES +524 -1
  4. data/Gemfile +82 -0
  5. data/LICENSE +1 -1
  6. data/README.de.rdoc +2093 -0
  7. data/README.es.rdoc +2091 -0
  8. data/README.fr.rdoc +2116 -0
  9. data/README.hu.rdoc +607 -0
  10. data/README.jp.rdoc +514 -23
  11. data/README.pt-br.rdoc +647 -0
  12. data/README.pt-pt.rdoc +646 -0
  13. data/README.rdoc +1580 -205
  14. data/README.ru.rdoc +2015 -0
  15. data/README.zh.rdoc +1816 -0
  16. data/Rakefile +110 -44
  17. data/examples/chat.rb +61 -0
  18. data/examples/simple.rb +3 -0
  19. data/examples/stream.ru +26 -0
  20. data/lib/sinatra.rb +0 -3
  21. data/lib/sinatra/base.rb +923 -393
  22. data/lib/sinatra/main.rb +9 -7
  23. data/lib/sinatra/showexceptions.rb +37 -4
  24. data/lib/sinatra/version.rb +3 -0
  25. data/sinatra-base.gemspec +15 -91
  26. data/test/base_test.rb +2 -2
  27. data/test/builder_test.rb +32 -2
  28. data/test/coffee_test.rb +92 -0
  29. data/test/contest.rb +62 -28
  30. data/test/creole_test.rb +65 -0
  31. data/test/delegator_test.rb +162 -0
  32. data/test/encoding_test.rb +20 -0
  33. data/test/erb_test.rb +25 -2
  34. data/test/extensions_test.rb +1 -1
  35. data/test/filter_test.rb +226 -8
  36. data/test/haml_test.rb +8 -2
  37. data/test/helper.rb +47 -0
  38. data/test/helpers_test.rb +1287 -80
  39. data/test/integration/app.rb +62 -0
  40. data/test/integration_helper.rb +208 -0
  41. data/test/integration_test.rb +82 -0
  42. data/test/less_test.rb +36 -6
  43. data/test/liquid_test.rb +59 -0
  44. data/test/mapped_error_test.rb +84 -7
  45. data/test/markaby_test.rb +80 -0
  46. data/test/markdown_test.rb +81 -0
  47. data/test/middleware_test.rb +1 -1
  48. data/test/nokogiri_test.rb +69 -0
  49. data/test/rack_test.rb +45 -0
  50. data/test/radius_test.rb +59 -0
  51. data/test/rdoc_test.rb +66 -0
  52. data/test/readme_test.rb +136 -0
  53. data/test/request_test.rb +13 -1
  54. data/test/response_test.rb +21 -2
  55. data/test/result_test.rb +5 -5
  56. data/test/route_added_hook_test.rb +1 -1
  57. data/test/routing_test.rb +328 -13
  58. data/test/sass_test.rb +48 -18
  59. data/test/scss_test.rb +88 -0
  60. data/test/server_test.rb +4 -3
  61. data/test/settings_test.rb +191 -21
  62. data/test/sinatra_test.rb +5 -1
  63. data/test/slim_test.rb +88 -0
  64. data/test/static_test.rb +89 -5
  65. data/test/streaming_test.rb +140 -0
  66. data/test/templates_test.rb +143 -4
  67. data/test/textile_test.rb +65 -0
  68. data/test/views/a/in_a.str +1 -0
  69. data/test/views/ascii.erb +2 -0
  70. data/test/views/b/in_b.str +1 -0
  71. data/test/views/calc.html.erb +1 -0
  72. data/test/views/explicitly_nested.str +1 -0
  73. data/test/views/hello.coffee +1 -0
  74. data/test/views/hello.creole +1 -0
  75. data/test/views/hello.liquid +1 -0
  76. data/test/views/hello.mab +1 -0
  77. data/test/views/hello.md +1 -0
  78. data/test/views/hello.nokogiri +1 -0
  79. data/test/views/hello.radius +1 -0
  80. data/test/views/hello.rdoc +1 -0
  81. data/test/views/hello.sass +1 -1
  82. data/test/views/hello.scss +3 -0
  83. data/test/views/hello.slim +1 -0
  84. data/test/views/hello.str +1 -0
  85. data/test/views/hello.textile +1 -0
  86. data/test/views/hello.yajl +1 -0
  87. data/test/views/layout2.liquid +2 -0
  88. data/test/views/layout2.mab +2 -0
  89. data/test/views/layout2.nokogiri +3 -0
  90. data/test/views/layout2.radius +2 -0
  91. data/test/views/layout2.slim +3 -0
  92. data/test/views/layout2.str +2 -0
  93. data/test/views/nested.str +1 -0
  94. data/test/views/utf8.erb +2 -0
  95. data/test/yajl_test.rb +80 -0
  96. metadata +126 -91
  97. data/lib/sinatra/tilt.rb +0 -746
  98. data/test/erubis_test.rb +0 -82
  99. data/test/views/error.erubis +0 -3
  100. data/test/views/hello.erubis +0 -1
  101. data/test/views/layout2.erubis +0 -2
@@ -1,9 +1,9 @@
1
1
  = Sinatra
2
+ <i>注) 本文書は英語から翻訳したものであり、その内容が最新でない場合もあります。最新の情報はオリジナルの英語版を参照して下さい。</i>
2
3
 
3
4
  SinatraはRubyで下記のような最小労力で手早くウェブアプリケーションを作成するためのDSLです。
4
5
 
5
6
  # myapp.rb
6
- require 'rubygems'
7
7
  require 'sinatra'
8
8
  get '/' do
9
9
  'Hello world!'
@@ -11,8 +11,8 @@ SinatraはRubyで下記のような最小労力で手早くウェブアプリケ
11
11
 
12
12
  gemをインストールして動かしてみる。
13
13
 
14
- sudo gem install sinatra
15
- ruby myapp.rb
14
+ gem install sinatra
15
+ ruby -rubygems myapp.rb
16
16
 
17
17
  http://localhost:4567 を見る。
18
18
 
@@ -67,6 +67,12 @@ Sinatraでは、ルートはHTTPメソッドとURLマッチングパターンが
67
67
  params[:splat] # => ["path/to/file", "xml"]
68
68
  end
69
69
 
70
+ ブロックパラーメータを使用した場合:
71
+
72
+ get '/download/*.*' do |path, ext|
73
+ [path, ext] # => ["path/to/file", "xml"]
74
+ end
75
+
70
76
  正規表現を使ったルート:
71
77
 
72
78
  get %r{/hello/([\w]+)} do
@@ -79,6 +85,9 @@ Sinatraでは、ルートはHTTPメソッドとURLマッチングパターンが
79
85
  "Hello, #{c}!"
80
86
  end
81
87
 
88
+
89
+ === 条件
90
+
82
91
  ルートにはユーザエージェントのようなさまざまな条件を含めることができます。
83
92
 
84
93
  get '/foo', :agent => /Songbird (\d\.\d)[\d\/]*?/ do
@@ -89,12 +98,64 @@ Sinatraでは、ルートはHTTPメソッドとURLマッチングパターンが
89
98
  # Matches non-songbird browsers
90
99
  end
91
100
 
101
+ ほかに+host_name+と+provides+条件が利用可能です:
102
+
103
+ get '/', :host_name => /^admin\./ do
104
+ "Admin Area, Access denied!"
105
+ end
106
+
107
+ get '/', :provides => 'html' do
108
+ haml :index
109
+ end
110
+
111
+ get '/', :provides => ['rss', 'atom', 'xml'] do
112
+ builder :feed
113
+ end
114
+
115
+ 独自の条件を定義することも簡単にできます:
116
+
117
+ set(:probability) { |value| condition { rand <= value } }
118
+
119
+ get '/win_a_car', :probability => 0.1 do
120
+ "You won!"
121
+ end
122
+
123
+ get '/win_a_car' do
124
+ "Sorry, you lost."
125
+ end
126
+
127
+
128
+ === 戻り値
129
+
130
+ ルートブロックの戻り値は、HTTPクライアントまたはRackスタックでの次のミドルウェアに渡されるレスポンスボディを決定します。
131
+
132
+ これは大抵の場合、上の例のように文字列ですが、それ以外の値も使用することができます。
133
+
134
+ Rackレスポンス、Rackボディオブジェクト、HTTPステータスコードのいずれかとして
135
+ 妥当なオブジェクトであればどのようなオブジェクトでも返すことができます:
136
+
137
+ * 3要素の配列: <tt>[ステータス(Fixnum), ヘッダ(Hash), レスポンスボディ(#eachに応答する)]</tt>
138
+ * 2要素の配列: <tt>[ステータス(Fixnum), レスポンスボディ(#eachに応答する)]</tt>
139
+ * <tt>#each</tt>に応答し、与えられたブロックに文字列を渡すオブジェクト
140
+ * ステータスコードを表現するFixnum
141
+
142
+ そのように、例えばストリーミングの例を簡単に実装することができます:
143
+
144
+ class Stream
145
+ def each
146
+ 100.times { |i| yield "#{i}\n" }
147
+ end
148
+ end
149
+
150
+ get('/') { Stream.new }
151
+
152
+
92
153
  == 静的ファイル
93
154
 
94
155
  静的ファイルは<tt>./public</tt>ディレクトリから配信されます。
95
- <tt>:public</tt>オプションを指定することで別の場所を指定することができます。
156
+ <tt>:public_folder</tt>オプションを指定することで別の場所を指定することができます。
96
157
 
97
- set :public, File.dirname(__FILE__) + '/static'
158
+ set :public_folder, File.dirname(__FILE__) + '/static'
98
159
 
99
160
  注意: この静的ファイル用のディレクトリ名はURL中に含まれません。
100
161
  例えば、<tt>./public/css/style.css</tt>は<tt>http://example.com/css/style.css</tt>でアクセスできます。
@@ -114,7 +175,7 @@ Sinatraでは、ルートはHTTPメソッドとURLマッチングパターンが
114
175
 
115
176
  hamlを使うにはhamlライブラリが必要です:
116
177
 
117
- ## hamlを読み込みます
178
+ # hamlを読み込みます
118
179
  require 'haml'
119
180
 
120
181
  get '/' do
@@ -123,7 +184,7 @@ hamlを使うにはhamlライブラリが必要です:
123
184
 
124
185
  <tt>./views/index.haml</tt>を表示します。
125
186
 
126
- {Haml's options}[http://haml.hamptoncatlin.com/docs/rdoc/classes/Haml.html]
187
+ {Haml's options}[http://haml-lang.com/docs/yardoc/file.HAML_REFERENCE.html#options]
127
188
  はSinatraの設定でグローバルに設定することができます。
128
189
  {Options and Configurations}[http://www.sinatrarb.com/configuration.html],
129
190
  を参照してそれぞれ設定を上書きして下さい。
@@ -137,7 +198,7 @@ hamlを使うにはhamlライブラリが必要です:
137
198
 
138
199
  === Erb テンプレート
139
200
 
140
- ## erbを読み込みます
201
+ # erbを読み込みます
141
202
  require 'erb'
142
203
 
143
204
  get '/' do
@@ -146,35 +207,59 @@ hamlを使うにはhamlライブラリが必要です:
146
207
 
147
208
  <tt>./views/index.erb</tt>を表示します。
148
209
 
210
+ === Erubis
211
+
212
+ erubisテンプレートを表示するには、erubisライブラリが必要です:
213
+
214
+ # erubisを読み込みます
215
+ require 'erubis'
216
+
217
+ get '/' do
218
+ erubis :index
219
+ end
220
+
221
+ <tt>./views/index.erubis</tt>を表示します。
222
+
149
223
  === Builder テンプレート
150
224
 
151
225
  builderを使うにはbuilderライブラリが必要です:
152
226
 
153
- ## builderを読み込みます
227
+ # builderを読み込みます
154
228
  require 'builder'
155
229
 
156
230
  get '/' do
157
- content_type 'application/xml', :charset => 'utf-8'
158
231
  builder :index
159
232
  end
160
233
 
161
234
  <tt>./views/index.builder</tt>を表示します。
162
235
 
236
+ === 鋸 テンプレート
237
+
238
+ 鋸を使うには鋸ライブラリが必要です:
239
+
240
+ # 鋸を読み込みます
241
+ require 'nokogiri'
242
+
243
+ get '/' do
244
+ nokogiri :index
245
+ end
246
+
247
+ <tt>./views/index.nokogiri</tt>を表示します。
248
+
163
249
  === Sass テンプレート
164
250
 
165
251
  Sassテンプレートを使うにはsassライブラリが必要です:
166
252
 
167
- ## hamlかsassを読み込みます
253
+ # hamlかsassを読み込みます
168
254
  require 'sass'
169
255
 
170
256
  get '/stylesheet.css' do
171
- content_type 'text/css', :charset => 'utf-8'
172
257
  sass :stylesheet
173
258
  end
174
259
 
175
260
  <tt>./views/stylesheet.sass</tt>を表示します。
176
261
 
177
- {Sass' options}[http://haml.hamptoncatlin.com/docs/rdoc/classes/Sass.html]
262
+ {Sass' options}[http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#options]
178
263
  はSinatraの設定でグローバルに設定することができます。
179
264
  see {Options and Configurations}[http://www.sinatrarb.com/configuration.html],
180
265
  を参照してそれぞれ設定を上書きして下さい。
@@ -182,10 +267,203 @@ see {Options and Configurations}[http://www.sinatrarb.com/configuration.html],
182
267
  set :sass, {:style => :compact } # デフォルトのSass styleは :nested
183
268
 
184
269
  get '/stylesheet.css' do
185
- content_type 'text/css', :charset => 'utf-8'
186
270
  sass :stylesheet, :sass_options => {:style => :expanded } # 上書き
187
271
  end
188
272
 
273
+ === Scss テンプレート
274
+
275
+ Scssテンプレートを使うにはsassライブラリが必要です:
276
+
277
+ # hamlかsassを読み込みます
278
+ require 'sass'
279
+
280
+ get '/stylesheet.css' do
281
+ scss :stylesheet
282
+ end
283
+
284
+ <tt>./views/stylesheet.scss</tt>を表示します。
285
+
286
+ {Sass' options}[http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#options]
287
+ はSinatraの設定でグローバルに設定することができます。
288
+ see {Options and Configurations}[http://www.sinatrarb.com/configuration.html],
289
+ を参照してそれぞれ設定を上書きして下さい。
290
+
291
+ set :scss, :style => :compact # デフォルトのScss styleは:nested
292
+
293
+ get '/stylesheet.css' do
294
+ scss :stylesheet, :style => :expanded # 上書き
295
+ end
296
+
297
+ === Less テンプレート
298
+
299
+ Lessテンプレートを使うにはlessライブラリが必要です:
300
+
301
+ # lessを読み込みます
302
+ require 'less'
303
+
304
+ get '/stylesheet.css' do
305
+ less :stylesheet
306
+ end
307
+
308
+ <tt>./views/stylesheet.less</tt>を表示します。
309
+
310
+ === Liquid テンプレート
311
+
312
+ Liquidテンプレートを使うにはliquidライブラリが必要です:
313
+
314
+ # liquidを読み込みます
315
+ require 'liquid'
316
+
317
+ get '/' do
318
+ liquid :index
319
+ end
320
+
321
+ <tt>./views/index.liquid</tt>を表示します。
322
+
323
+ LiquidテンプレートからRubyのメソッド(+yield+を除く)を呼び出すことができないため、
324
+ ほぼ全ての場合にlocalsを指定する必要があるでしょう:
325
+
326
+ liquid :index, :locals => { :key => 'value' }
327
+
328
+ === Markdown テンプレート
329
+
330
+ Markdownテンプレートを使うにはrdiscountライブラリが必要です:
331
+
332
+ # rdiscountを読み込みます
333
+ require "rdiscount"
334
+
335
+ get '/' do
336
+ markdown :index
337
+ end
338
+
339
+ <tt>./views/index.markdown</tt>を表示します。(+md+と+mkd+も妥当な拡張子です)
340
+
341
+ markdownからメソッドを呼び出すことも、localsに変数を渡すこともできません。
342
+ それゆえ、他のレンダリングエンジンとの組み合わせで使うのが普通です:
343
+
344
+ erb :overview, :locals => { :text => markdown(:introduction) }
345
+
346
+ 他のテンプレートからmarkdownメソッドを呼び出してもよいことに注意してください:
347
+
348
+ %h1 Hello From Haml!
349
+ %p= markdown(:greetings)
350
+
351
+ === Textile テンプレート
352
+
353
+ Textileテンプレートを使うにはRedClothライブラリが必要です:
354
+
355
+ # redclothを読み込みます
356
+ require "redcloth"
357
+
358
+ get '/' do
359
+ textile :index
360
+ end
361
+
362
+ <tt>./views/index.textile</tt>を表示します。
363
+
364
+ textileからメソッドを呼び出すことも、localsに変数を渡すこともできません。
365
+ それゆえ、他のレンダリングエンジンとの組み合わせで使うのが普通です:
366
+
367
+ erb :overview, :locals => { :text => textile(:introduction) }
368
+
369
+ 他のテンプレートからtextileメソッドを呼び出してもよいことに注意してください:
370
+
371
+ %h1 Hello From Haml!
372
+ %p= textile(:greetings)
373
+
374
+ === RDoc テンプレート
375
+
376
+ RDocテンプレートを使うにはRDocライブラリが必要です:
377
+
378
+ # rdoc/markup/to_htmlを読み込みます
379
+ require "rdoc"
380
+ require "rdoc/markup/to_html"
381
+
382
+ get '/' do
383
+ rdoc :index
384
+ end
385
+
386
+ <tt>./views/index.rdoc</tt>を表示します。
387
+
388
+ rdocからメソッドを呼び出すことも、localsに変数を渡すこともできません。
389
+ それゆえ、他のレンダリングエンジンとの組み合わせで使うのが普通です:
390
+
391
+ erb :overview, :locals => { :text => rdoc(:introduction) }
392
+
393
+ 他のテンプレートからrdocメソッドを呼び出してもよいことに注意してください:
394
+
395
+ %h1 Hello From Haml!
396
+ %p= rdoc(:greetings)
397
+
398
+ === Radius テンプレート
399
+
400
+ Radiusテンプレートを使うにはradiusライブラリが必要です:
401
+
402
+ # radiusを読み込みます
403
+ require 'radius'
404
+
405
+ get '/' do
406
+ radius :index
407
+ end
408
+
409
+ <tt>./views/index.radius</tt>を表示します。
410
+
411
+ RadiusテンプレートからRubyのメソッド(+yield+を除く)を呼び出すことができないため、
412
+ ほぼ全ての場合にlocalsを指定する必要があるでしょう:
413
+
414
+ radius :index, :locals => { :key => 'value' }
415
+
416
+ === Markaby テンプレート
417
+
418
+ Markabyテンプレートを使うにはmarkabyライブラリが必要です:
419
+
420
+ # markabyを読み込みます
421
+ require 'markaby'
422
+
423
+ get '/' do
424
+ markaby :index
425
+ end
426
+
427
+ <tt>./views/index.mab</tt>を表示します。
428
+
429
+ === Slim テンプレート
430
+
431
+ Slimテンプレートを使うにはslimライブラリが必要です:
432
+
433
+ # slimを読み込みます
434
+ require 'slim'
435
+
436
+ get '/' do
437
+ slim :index
438
+ end
439
+
440
+ <tt>./views/index.slim</tt>を表示します。
441
+
442
+ === Creole テンプレート
443
+
444
+ Creoleテンプレートを使うにはcreoleライブラリが必要です:
445
+
446
+ # creoleを読み込みます
447
+ require 'creole'
448
+
449
+ get '/' do
450
+ creole :index
451
+ end
452
+
453
+ <tt>./views/index.creole</tt>を表示します。
454
+
455
+ === CoffeeScript テンプレート
456
+
457
+ CoffeeScriptテンプレートを表示するにはcoffee-scriptライブラリと`coffee`バイナリが必要です:
458
+
459
+ # coffee-scriptを読み込みます
460
+ require 'coffee-script'
461
+
462
+ get '/application.js' do
463
+ coffee :application
464
+ end
465
+
466
+ <tt>./views/application.coffee</tt>を表示します。
189
467
 
190
468
  === インラインテンプレート
191
469
 
@@ -235,7 +513,7 @@ see {Options and Configurations}[http://www.sinatrarb.com/configuration.html],
235
513
  %div.title Hello world!!!!!
236
514
 
237
515
  注意: sinatraをrequireするファイル内で定義されたファイル内テンプレートは自動的に読み込まれます。
238
- 他のファイルで定義されているテンプレートを使うには <tt>use_in_file_templates!</tt>メソッドで指定します。
516
+ 他のファイルで定義されているテンプレートを使うには <tt>enable :inline_templates</tt>を明示的に呼んでください。
239
517
 
240
518
  === 名前付きテンプレート
241
519
 
@@ -254,7 +532,7 @@ see {Options and Configurations}[http://www.sinatrarb.com/configuration.html],
254
532
  end
255
533
 
256
534
  「layout」というテンプレートが存在する場合、そのテンプレートファイルは他のテンプレートが
257
- 表示される度に使用されます。<tt>:layout => false</tt>.することでlayoutsを無効にできます。
535
+ 表示される度に使用されます。<tt>:layout => false</tt>することでlayoutsを無効にできます。
258
536
 
259
537
  get '/' do
260
538
  haml :index, :layout => !request.xhr?
@@ -291,12 +569,36 @@ beforeフィルタはリクエストされたコンテキストを実行する
291
569
  params[:splat] #=> 'bar/baz'
292
570
  end
293
571
 
572
+ afterフィルタは同じコンテキストにあるリクエストの後に評価され、
573
+ 同じくリクエストとレスポンスを変更することができます。
574
+ beforeフィルタとルートで設定されたインスタンス変数は、
575
+ afterフィルタからアクセスすることができます:
576
+
577
+ after do
578
+ puts response.status
579
+ end
580
+
581
+ フィルタにはオプションとしてパターンを渡すことができ、
582
+ この場合はリクエストのパスがパターンにマッチした場合のみフィルタが評価されます:
583
+
584
+ before '/protected/*' do
585
+ authenticate!
586
+ end
587
+
588
+ after '/create/:slug' do |slug|
589
+ session[:last_slug] = slug
590
+ end
591
+
294
592
  == 強制終了
295
593
 
296
594
  ルートかbeforeフィルタ内で直ちに実行を終了する方法:
297
595
 
298
596
  halt
299
597
 
598
+ ステータスを指定することができます:
599
+
600
+ halt 410
601
+
300
602
  body部を指定することもできます ...
301
603
 
302
604
  halt 'ここにbodyを書く'
@@ -305,6 +607,10 @@ body部を指定することもできます ...
305
607
 
306
608
  halt 401, '立ち去れ!'
307
609
 
610
+ ヘッダを指定:
611
+
612
+ halt 402, {'Content-Type' => 'text/plain'}, 'リベンジ'
613
+
308
614
  == パッシング(Passing)
309
615
 
310
616
  ルートは<tt>pass</tt>を使って次のルートに飛ばすことができます:
@@ -321,6 +627,53 @@ body部を指定することもできます ...
321
627
  ルートブロックからすぐに抜け出し、次にマッチするルートを実行します。
322
628
  マッチするルートが見当たらない場合は404が返されます。
323
629
 
630
+ == リクエストオブジェクトへのアクセス
631
+
632
+ 受信するリクエストオブジェクトは、`request`メソッドを通じてリクエストレベル(フィルタ、ルート、エラーハンドラ)からアクセスすることができます:
633
+
634
+ # アプリケーションが http://example.com/example で動作している場合
635
+ get '/foo' do
636
+ request.body # クライアントによって送信されたリクエストボディ(下記参照)
637
+ request.scheme # "http"
638
+ request.script_name # "/example"
639
+ request.path_info # "/foo"
640
+ request.port # 80
641
+ request.request_method # "GET"
642
+ request.query_string # ""
643
+ request.content_length # request.bodyの長さ
644
+ request.media_type # request.bodyのメディアタイプ
645
+ request.host # "example.com"
646
+ request.get? # true (他の動詞についても同様のメソッドあり)
647
+ request.form_data? # false
648
+ request["SOME_HEADER"] # SOME_HEADERヘッダの値
649
+ request.referer # クライアントのリファラまたは'/'
650
+ request.user_agent # ユーザエージェント (:agent 条件によって使用される)
651
+ request.cookies # ブラウザクッキーのハッシュ
652
+ request.xhr? # Ajaxリクエストかどうか
653
+ request.url # "http://example.com/example/foo"
654
+ request.path # "/example/foo"
655
+ request.ip # クライアントのIPアドレス
656
+ request.secure? # false
657
+ request.env # Rackによって渡された生のenvハッシュ
658
+ end
659
+
660
+ <tt>script_name</tt>や<tt>path_info</tt>などのオプションは次のように利用することもできます:
661
+
662
+ before { request.path_info = "/" }
663
+
664
+ get "/" do
665
+ "全てのリクエストはここに来る"
666
+ end
667
+
668
+ <tt>request.body</tt>はIOまたはStringIOのオブジェクトです:
669
+
670
+ post "/api" do
671
+ request.body.rewind # 既に読まれているときのため
672
+ data = JSON.parse request.body.read
673
+ "Hello #{data['name']}!"
674
+ end
675
+
676
+
324
677
  == 設定
325
678
 
326
679
  どの環境でも起動時に1回だけ実行されます。
@@ -329,13 +682,13 @@ body部を指定することもできます ...
329
682
  ...
330
683
  end
331
684
 
332
- 環境変数<tt>:production</tt>(RACK_ENV環境変数) がセットされている時だけ実行する方法:
685
+ 環境(RACK_ENV環境変数)が<tt>:production</tt>に設定されている時だけ実行する方法:
333
686
 
334
687
  configure :production do
335
688
  ...
336
689
  end
337
690
 
338
- 環境変数<tt>:production</tt> か<tt>:test</tt>の場合に設定する方法:
691
+ 環境が<tt>:production</tt>か<tt>:test</tt>の場合に設定する方法:
339
692
 
340
693
  configure :production, :test do
341
694
  ...
@@ -358,7 +711,7 @@ body部を指定することもできます ...
358
711
  === エラー
359
712
 
360
713
  +error+ ハンドラーはルートブロックかbeforeフィルタ内で例外が発生した時はいつでも発動します。
361
- block or before filter. 例外オブジェクトはRack変数<tt>sinatra.error</tt>から取得されます。
714
+ 例外オブジェクトはRack変数<tt>sinatra.error</tt>から取得できます。
362
715
 
363
716
  error do
364
717
  'エラーが発生しました。 - ' + env['sinatra.error'].name
@@ -367,7 +720,7 @@ block or before filter. 例外オブジェクトはRack変数<tt>sinatra.error</
367
720
  エラーをカスタマイズする場合は、
368
721
 
369
722
  error MyCustomError do
370
- 'エラーメッセージ...' + request.env['sinatra.error'].message
723
+ 'エラーメッセージ...' + env['sinatra.error'].message
371
724
  end
372
725
 
373
726
  と書いておいて,下記のように呼び出します。
@@ -380,6 +733,23 @@ block or before filter. 例外オブジェクトはRack変数<tt>sinatra.error</
380
733
 
381
734
  エラーメッセージ... 何かがまずかったようです
382
735
 
736
+ あるいは、ステータスコードに対応するエラーハンドラを設定することもできます:
737
+
738
+ error 403 do
739
+ 'Access forbidden'
740
+ end
741
+
742
+ get '/secret' do
743
+ 403
744
+ end
745
+
746
+ 範囲指定もできます:
747
+
748
+ error 400..510 do
749
+ 'Boom'
750
+ end
751
+
752
+
383
753
  開発環境として実行している場合、Sinatraは特別な<tt>not_found</tt>と<tt>error</tt>ハンドラーを
384
754
  インストールしています。
385
755
 
@@ -390,6 +760,10 @@ block or before filter. 例外オブジェクトはRack変数<tt>sinatra.error</
390
760
 
391
761
  mime_type :foo, 'text/foo'
392
762
 
763
+ これはcontent_typeヘルパで利用することができます:
764
+
765
+ content_type :foo
766
+
393
767
  == Rackミドルウェア
394
768
 
395
769
  SinatraはRack[http://rack.rubyforge.org/]というRubyのWEBフレームワーク用の
@@ -496,16 +870,133 @@ Sinatra::Baseのサブクラスで使えるメソッドはトップレベルのD
496
870
  {Sinatra::Delegator mixin}[http://github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb#L1064]
497
871
  {included into the main namespace}[http://github.com/sinatra/sinatra/blob/master/lib/sinatra/main.rb#L25].
498
872
 
873
+ === Sinatraをミドルウェアとして利用する
874
+
875
+ Sinatraは他のRackミドルウェアを利用することができるだけでなく、
876
+ 全てのSinatraアプリケーションは、それ自体ミドルウェアとして別のRackエンドポイントの前に追加することが可能です。
877
+
878
+ このエンドポイントには、別のSinatraアプリケーションまたは他のRackベースのアプリケーション(Rails/Ramaze/Camping/...)が用いられるでしょう。
879
+
880
+ require 'sinatra/base'
881
+
882
+ class LoginScreen < Sinatra::Base
883
+ enable :sessions
884
+
885
+ get('/login') { haml :login }
886
+
887
+ post('/login') do
888
+ if params[:name] = 'admin' and params[:password] = 'admin'
889
+ session['user_name'] = params[:name]
890
+ else
891
+ redirect '/login'
892
+ end
893
+ end
894
+ end
895
+
896
+ class MyApp < Sinatra::Base
897
+ # middleware will run before filters
898
+ use LoginScreen
899
+
900
+ before do
901
+ unless session['user_name']
902
+ halt "Access denied, please <a href='/login'>login</a>."
903
+ end
904
+ end
905
+
906
+ get('/') { "Hello #{session['user_name']}." }
907
+ end
908
+
909
+ == スコープとバインディング
910
+
911
+ 現在のスコープはどのメソッドや変数が利用可能かを決定します。
912
+
913
+ === アプリケーション/クラスのスコープ
914
+
915
+ 全てのSinatraアプリケーションはSinatra::Baseのサブクラスに相当します。
916
+ もしトップレベルDSLを利用しているならば(<tt>require 'sinatra'</tt>)このクラスはSinatra::Applicationであり、
917
+ そうでなければ、あなたが明示的に作成したサブクラスです。
918
+ クラスレベルでは`get`や`before`のようなメソッドを持っています。
919
+ しかし`request`オブジェクトや`session`には、全てのリクエストのために1つのアプリケーションクラスが存在するためアクセスできません。
920
+
921
+ `set`によって作られたオプションはクラスレベルのメソッドです:
922
+
923
+ class MyApp < Sinatra::Base
924
+ # Hey, I'm in the application scope!
925
+ set :foo, 42
926
+ foo # => 42
927
+
928
+ get '/foo' do
929
+ # Hey, I'm no longer in the application scope!
930
+ end
931
+ end
932
+
933
+ 次の場所ではアプリケーションスコープバインディングを持ちます:
934
+
935
+ * アプリケーションのクラス本体
936
+ * 拡張によって定義されたメソッド
937
+ * `helpers`に渡されたブロック
938
+ * `set`の値として使われるProcまたはブロック
939
+
940
+ このスコープオブジェクト(クラス)は次のように利用できます:
941
+
942
+ * configureブロックに渡されたオブジェクト経由(<tt>configure { |c| ... }</tt>)
943
+ * リクエストスコープの中での`settings`
944
+
945
+ === リクエスト/インスタンスのスコープ
946
+
947
+ やってくるリクエストごとに、あなたのアプリケーションクラスの新しいインスタンスが作成され、全てのハンドラブロックがそのスコープで実行されます。
948
+ このスコープの内側からは`request`や`session`オブジェクトにアクセスすることができ、`erb`や`haml`のような表示メソッドを呼び出すことができます。
949
+ リクエストスコープの内側からは、`settings`ヘルパによってアプリケーションスコープにアクセスすることができます。
950
+
951
+ class MyApp < Sinatra::Base
952
+ # Hey, I'm in the application scope!
953
+ get '/define_route/:name' do
954
+ # Request scope for '/define_route/:name'
955
+ @value = 42
956
+
957
+ settings.get("/#{params[:name]}") do
958
+ # Request scope for "/#{params[:name]}"
959
+ @value # => nil (not the same request)
960
+ end
961
+
962
+ "Route defined!"
963
+ end
964
+ end
965
+
966
+ 次の場所ではリクエストスコープバインディングを持ちます:
967
+
968
+ * get/head/post/put/delete ブロック
969
+ * before/after フィルタ
970
+ * helper メソッド
971
+ * テンプレート/ビュー
972
+
973
+ === デリゲートスコープ
974
+
975
+ デリゲートスコープは、単にクラススコープにメソッドを転送します。
976
+ しかしながら、クラスのバインディングを持っていないため、クラススコープと全く同じふるまいをするわけではありません:
977
+ 委譲すると明示的に示されたメソッドのみが利用可能であり、またクラススコープと変数/状態を共有することはできません(注: 異なった`self`を持っています)。
978
+ <tt>Sinatra::Delegator.delegate :method_name</tt>を呼び出すことによってデリゲートするメソッドを明示的に追加することができます。
979
+
980
+ 次の場所ではデリゲートスコープを持ちます:
981
+
982
+ * もし<tt>require "sinatra"</tt>しているならば、トップレベルバインディング
983
+ * `Sinatra::Delegator` mixinでextendされたオブジェクト
984
+
985
+ コードをご覧ください: ここでは
986
+ {Sinatra::Delegator mixin}[http://github.com/sinatra/sinatra/blob/ceac46f0bc129a6e994a06100aa854f606fe5992/lib/sinatra/base.rb#L1128]
987
+ は{main 名前空間にincludeされています}[http://github.com/sinatra/sinatra/blob/ceac46f0bc129a6e994a06100aa854f606fe5992/lib/sinatra/main.rb#L28].
988
+
499
989
  == コマンドライン
500
990
 
501
991
  Sinatraアプリケーションは直接実行できます。
502
992
 
503
- ruby myapp.rb [-h] [-x] [-e ENVIRONMENT] [-p PORT] [-s HANDLER]
993
+ ruby myapp.rb [-h] [-x] [-e ENVIRONMENT] [-p PORT] [-o HOST] [-s HANDLER]
504
994
 
505
995
  オプション:
506
996
 
507
997
  -h # ヘルプ
508
998
  -p # ポート指定(デフォルトは4567)
999
+ -o # ホスト指定(デフォルトは0.0.0.0)
509
1000
  -e # 環境を指定 (デフォルトはdevelopment)
510
1001
  -s # rackserver/handlerを指定 (デフォルトはthin)
511
1002
  -x # mutex lockを付ける (デフォルトはoff)
@@ -519,7 +1010,7 @@ Sinatraの開発版を使いたい場合は、ローカルに開発版を落と
519
1010
  git clone git://github.com/sinatra/sinatra.git
520
1011
  ruby -Isinatra/lib myapp.rb
521
1012
 
522
- <tt>sinatra/lib</tt>ディレクトリをto the<tt>LOAD_PATH</tt>に追加する方法もあります。
1013
+ <tt>sinatra/lib</tt>ディレクトリをアプリケーションの<tt>LOAD_PATH</tt>に追加する方法もあります。
523
1014
 
524
1015
  $LOAD_PATH.unshift File.dirname(__FILE__) + '/sinatra/lib'
525
1016
  require 'rubygems'
@@ -546,7 +1037,7 @@ Sinatraのソースを更新する方法:
546
1037
  ニュース、他のリソースへのリンクがあります。
547
1038
  * {プロジェクトに参加(貢献)する}[http://sinatra.github.com/contributing.html] - バグレポート
548
1039
  パッチの送信、サポートなど
549
- * {Lighthouse}[http://sinatra.lighthouseapp.com] - チケット管理とリリース計画
1040
+ * {Issue tracker}[http://github.com/sinatra/sinatra/issues] - チケット管理とリリース計画
550
1041
  * {Twitter}[http://twitter.com/sinatra]
551
1042
  * {メーリングリスト}[http://groups.google.com/group/sinatrarb]
552
1043
  * {IRC: #sinatra}[irc://chat.freenode.net/#sinatra] on http://freenode.net