sinatra 1.4.0.c → 1.4.0.d

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.

@@ -0,0 +1,1097 @@
1
+ # Sinatra
2
+
3
+ *注)
4
+ 本文書は英語から翻訳したものであり、その内容が最新でない場合もあります。最新の情報はオリジナルの英語版を参照して下さい。*
5
+
6
+ [DSL](http://ja.wikipedia.org/wiki/ドメイン固有言語)です。
7
+
8
+ # myapp.rb
9
+ require 'sinatra'
10
+ get '/' do
11
+ 'Hello world!'
12
+ end
13
+
14
+ gemをインストールして動かしてみる。
15
+
16
+ gem install sinatra
17
+ ruby myapp.rb
18
+
19
+ [localhost:4567](http://localhost:4567) を見る。
20
+
21
+ ## ルート
22
+
23
+ Sinatraでは、ルートはHTTPメソッドとURLマッチングパターンがペアになっています。
24
+ ルートはブロックに結び付けられています。
25
+
26
+ get '/' do
27
+ .. 何か見せる ..
28
+ end
29
+
30
+ post '/' do
31
+ .. 何か生成する ..
32
+ end
33
+
34
+ put '/' do
35
+ .. 何か更新する ..
36
+ end
37
+
38
+ delete '/' do
39
+ .. 何か削除する ..
40
+ end
41
+
42
+ ルートは定義された順番にマッチします。
43
+ リクエストに最初にマッチしたルートが呼び出されます。
44
+
45
+ ルートのパターンは名前付きパラメータを含むことができ、
46
+ `params`ハッシュで取得できます。
47
+
48
+ get '/hello/:name' do
49
+ # matches "GET /hello/foo" and "GET /hello/bar"
50
+ # params[:name] is 'foo' or 'bar'
51
+ "Hello #{params[:name]}!"
52
+ end
53
+
54
+ また、ブロックパラメータで名前付きパラメータにアクセスすることもできます。
55
+
56
+ get '/hello/:name' do |n|
57
+ "Hello #{n}!"
58
+ end
59
+
60
+ ルートパターンはsplat(またはワイルドカード)を含むこともでき、
61
+ `params[:splat]` で取得できます。
62
+
63
+ get '/say/*/to/*' do
64
+ # matches /say/hello/to/world
65
+ params[:splat] # => ["hello", "world"]
66
+ end
67
+
68
+ get '/download/*.*' do
69
+ # matches /download/path/to/file.xml
70
+ params[:splat] # => ["path/to/file", "xml"]
71
+ end
72
+
73
+ ブロックパラーメータを使用した場合:
74
+
75
+ get '/download/*.*' do |path, ext|
76
+ [path, ext] # => ["path/to/file", "xml"]
77
+ end
78
+
79
+ 正規表現を使ったルート:
80
+
81
+ get %r{/hello/([\w]+)} do
82
+ "Hello, #{params[:captures].first}!"
83
+ end
84
+
85
+ ブロックパラーメータを使用した場合:
86
+
87
+ get %r{/hello/([\w]+)} do |c|
88
+ "Hello, #{c}!"
89
+ end
90
+
91
+ ### 条件
92
+
93
+ ルートにはユーザエージェントのようなさまざまな条件を含めることができます。
94
+
95
+ get '/foo', :agent => /Songbird (\d\.\d)[\d\/]*?/ do
96
+ "You're using Songbird version #{params[:agent][0]}"
97
+ end
98
+
99
+ get '/foo' do
100
+ # Matches non-songbird browsers
101
+ end
102
+
103
+ ほかに`host_name`と`provides`条件が利用可能です:
104
+
105
+ get '/', :host_name => /^admin\./ do
106
+ "Admin Area, Access denied!"
107
+ end
108
+
109
+ get '/', :provides => 'html' do
110
+ haml :index
111
+ end
112
+
113
+ get '/', :provides => ['rss', 'atom', 'xml'] do
114
+ builder :feed
115
+ end
116
+
117
+ 独自の条件を定義することも簡単にできます:
118
+
119
+ set(:probability) { |value| condition { rand <= value } }
120
+
121
+ get '/win_a_car', :probability => 0.1 do
122
+ "You won!"
123
+ end
124
+
125
+ get '/win_a_car' do
126
+ "Sorry, you lost."
127
+ end
128
+
129
+ ### 戻り値
130
+
131
+ ルートブロックの戻り値は、HTTPクライアントまたはRackスタックでの次のミドルウェアに渡されるレスポンスボディを決定します。
132
+
133
+ これは大抵の場合、上の例のように文字列ですが、それ以外の値も使用することができます。
134
+
135
+ Rackレスポンス、Rackボディオブジェクト、HTTPステータスコードのいずれかとして
136
+ 妥当なオブジェクトであればどのようなオブジェクトでも返すことができます:
137
+
138
+ - 3要素の配列:
139
+ `[ステータス(Fixnum), ヘッダ(Hash), レスポンスボディ(#eachに応答する)]`
140
+
141
+ - 2要素の配列:
142
+ `[ステータス(Fixnum), レスポンスボディ(#eachに応答する)]`
143
+
144
+ - `#each`に応答し、与えられたブロックに文字列を渡すオブジェクト
145
+
146
+ - ステータスコードを表現するFixnum
147
+
148
+ そのように、例えばストリーミングの例を簡単に実装することができます:
149
+
150
+ class Stream
151
+ def each
152
+ 100.times { |i| yield "#{i}\n" }
153
+ end
154
+ end
155
+
156
+ get('/') { Stream.new }
157
+
158
+ ## 静的ファイル
159
+
160
+ 静的ファイルは`./public`ディレクトリから配信されます。
161
+ `:public_folder`オプションを指定することで別の場所を指定することができます。
162
+
163
+ set :public_folder, File.dirname(__FILE__) + '/static'
164
+
165
+ 注意: この静的ファイル用のディレクトリ名はURL中に含まれません。
166
+ 例えば、`./public/css/style.css`は`http://example.com/css/style.css`でアクセスできます。
167
+
168
+ ## ビュー / テンプレート
169
+
170
+ テンプレートは`./views`ディレクトリ下に配置されています。
171
+ 他のディレクトリを使用する場合の例:
172
+
173
+ set :views, File.dirname(__FILE__) + '/templates'
174
+
175
+ テンプレートはシンボルを使用して参照させることを覚えておいて下さい。
176
+ サブデレクトリでもこの場合は`:'subdir/template'`のようにします。
177
+ レンダリングメソッドは文字列が渡されると、そのまま文字列を出力します。
178
+
179
+ ### Haml テンプレート
180
+
181
+ hamlを使うにはhamlライブラリが必要です:
182
+
183
+ # hamlを読み込みます
184
+ require 'haml'
185
+
186
+ get '/' do
187
+ haml :index
188
+ end
189
+
190
+ `./views/index.haml`を表示します。
191
+
192
+ [Haml’s
193
+ options](http://haml.info/docs/yardoc/file.HAML_REFERENCE.html#options)
194
+ はSinatraの設定でグローバルに設定することができます。 [Options and
195
+ Configurations](http://www.sinatrarb.com/configuration.html),
196
+ を参照してそれぞれ設定を上書きして下さい。
197
+
198
+ set :haml, {:format => :html5 } # デフォルトのフォーマットは:xhtml
199
+
200
+ get '/' do
201
+ haml :index, :haml_options => {:format => :html4 } # 上書き
202
+ end
203
+
204
+ ### Erb テンプレート
205
+
206
+ # erbを読み込みます
207
+ require 'erb'
208
+
209
+ get '/' do
210
+ erb :index
211
+ end
212
+
213
+ `./views/index.erb`を表示します。
214
+
215
+ ### Erubis
216
+
217
+ erubisテンプレートを表示するには、erubisライブラリが必要です:
218
+
219
+ # erubisを読み込みます
220
+ require 'erubis'
221
+
222
+ get '/' do
223
+ erubis :index
224
+ end
225
+
226
+ `./views/index.erubis`を表示します。
227
+
228
+ ### Builder テンプレート
229
+
230
+ builderを使うにはbuilderライブラリが必要です:
231
+
232
+ # builderを読み込みます
233
+ require 'builder'
234
+
235
+ get '/' do
236
+ builder :index
237
+ end
238
+
239
+ `./views/index.builder`を表示します。
240
+
241
+ ### 鋸 テンプレート
242
+
243
+ 鋸を使うには鋸ライブラリが必要です:
244
+
245
+ # 鋸を読み込みます
246
+ require 'nokogiri'
247
+
248
+ get '/' do
249
+ nokogiri :index
250
+ end
251
+
252
+ `./views/index.nokogiri`を表示します。
253
+
254
+ ### Sass テンプレート
255
+
256
+ Sassテンプレートを使うにはsassライブラリが必要です:
257
+
258
+ # hamlかsassを読み込みます
259
+ require 'sass'
260
+
261
+ get '/stylesheet.css' do
262
+ sass :stylesheet
263
+ end
264
+
265
+ `./views/stylesheet.sass`を表示します。
266
+
267
+ [Sass’
268
+ options](http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#options)
269
+ はSinatraの設定でグローバルに設定することができます。 see [Options and
270
+ Configurations](http://www.sinatrarb.com/configuration.html),
271
+ を参照してそれぞれ設定を上書きして下さい。
272
+
273
+ set :sass, {:style => :compact } # デフォルトのSass styleは :nested
274
+
275
+ get '/stylesheet.css' do
276
+ sass :stylesheet, :sass_options => {:style => :expanded } # 上書き
277
+ end
278
+
279
+ ### Scss テンプレート
280
+
281
+ Scssテンプレートを使うにはsassライブラリが必要です:
282
+
283
+ # hamlかsassを読み込みます
284
+ require 'sass'
285
+
286
+ get '/stylesheet.css' do
287
+ scss :stylesheet
288
+ end
289
+
290
+ `./views/stylesheet.scss`を表示します。
291
+
292
+ [Sass’
293
+ options](http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#options)
294
+ はSinatraの設定でグローバルに設定することができます。 see [Options and
295
+ Configurations](http://www.sinatrarb.com/configuration.html),
296
+ を参照してそれぞれ設定を上書きして下さい。
297
+
298
+ set :scss, :style => :compact # デフォルトのScss styleは:nested
299
+
300
+ get '/stylesheet.css' do
301
+ scss :stylesheet, :style => :expanded # 上書き
302
+ end
303
+
304
+ ### Less テンプレート
305
+
306
+ Lessテンプレートを使うにはlessライブラリが必要です:
307
+
308
+ # lessを読み込みます
309
+ require 'less'
310
+
311
+ get '/stylesheet.css' do
312
+ less :stylesheet
313
+ end
314
+
315
+ `./views/stylesheet.less`を表示します。
316
+
317
+ ### Liquid テンプレート
318
+
319
+ Liquidテンプレートを使うにはliquidライブラリが必要です:
320
+
321
+ # liquidを読み込みます
322
+ require 'liquid'
323
+
324
+ get '/' do
325
+ liquid :index
326
+ end
327
+
328
+ `./views/index.liquid`を表示します。
329
+
330
+ LiquidテンプレートからRubyのメソッド(`yield`を除く)を呼び出すことができないため、
331
+ ほぼ全ての場合にlocalsを指定する必要があるでしょう:
332
+
333
+ liquid :index, :locals => { :key => 'value' }
334
+
335
+ ### Markdown テンプレート
336
+
337
+ Markdownテンプレートを使うにはrdiscountライブラリが必要です:
338
+
339
+ # rdiscountを読み込みます
340
+ require "rdiscount"
341
+
342
+ get '/' do
343
+ markdown :index
344
+ end
345
+
346
+ `./views/index.markdown`を表示します。(`md`と`mkd`も妥当な拡張子です)
347
+
348
+ markdownからメソッドを呼び出すことも、localsに変数を渡すこともできません。
349
+ それゆえ、他のレンダリングエンジンとの組み合わせで使うのが普通です:
350
+
351
+ erb :overview, :locals => { :text => markdown(:introduction) }
352
+
353
+ 他のテンプレートからmarkdownメソッドを呼び出してもよいことに注意してください:
354
+
355
+ %h1 Hello From Haml!
356
+ %p= markdown(:greetings)
357
+
358
+ ### Textile テンプレート
359
+
360
+ Textileテンプレートを使うにはRedClothライブラリが必要です:
361
+
362
+ # redclothを読み込みます
363
+ require "redcloth"
364
+
365
+ get '/' do
366
+ textile :index
367
+ end
368
+
369
+ `./views/index.textile`を表示します。
370
+
371
+ textileからメソッドを呼び出すことも、localsに変数を渡すこともできません。
372
+ それゆえ、他のレンダリングエンジンとの組み合わせで使うのが普通です:
373
+
374
+ erb :overview, :locals => { :text => textile(:introduction) }
375
+
376
+ 他のテンプレートからtextileメソッドを呼び出してもよいことに注意してください:
377
+
378
+ %h1 Hello From Haml!
379
+ %p= textile(:greetings)
380
+
381
+ ### RDoc テンプレート
382
+
383
+ RDocテンプレートを使うにはRDocライブラリが必要です:
384
+
385
+ # rdoc/markup/to_htmlを読み込みます
386
+ require "rdoc"
387
+ require "rdoc/markup/to_html"
388
+
389
+ get '/' do
390
+ rdoc :index
391
+ end
392
+
393
+ `./views/index.rdoc`を表示します。
394
+
395
+ rdocからメソッドを呼び出すことも、localsに変数を渡すこともできません。
396
+ それゆえ、他のレンダリングエンジンとの組み合わせで使うのが普通です:
397
+
398
+ erb :overview, :locals => { :text => rdoc(:introduction) }
399
+
400
+ 他のテンプレートからrdocメソッドを呼び出してもよいことに注意してください:
401
+
402
+ %h1 Hello From Haml!
403
+ %p= rdoc(:greetings)
404
+
405
+ ### Radius テンプレート
406
+
407
+ Radiusテンプレートを使うにはradiusライブラリが必要です:
408
+
409
+ # radiusを読み込みます
410
+ require 'radius'
411
+
412
+ get '/' do
413
+ radius :index
414
+ end
415
+
416
+ `./views/index.radius`を表示します。
417
+
418
+ RadiusテンプレートからRubyのメソッド(`yield`を除く)を呼び出すことができないため、
419
+ ほぼ全ての場合にlocalsを指定する必要があるでしょう:
420
+
421
+ radius :index, :locals => { :key => 'value' }
422
+
423
+ ### Markaby テンプレート
424
+
425
+ Markabyテンプレートを使うにはmarkabyライブラリが必要です:
426
+
427
+ # markabyを読み込みます
428
+ require 'markaby'
429
+
430
+ get '/' do
431
+ markaby :index
432
+ end
433
+
434
+ `./views/index.mab`を表示します。
435
+
436
+ ### RABL テンプレート
437
+
438
+ RABLテンプレートを使うにはrablライブラリが必要です:
439
+
440
+ # rablを読み込みます
441
+ require 'rabl'
442
+
443
+ get '/' do
444
+ rabl :index
445
+ end
446
+
447
+ `./views/index.rabl`を表示します。
448
+
449
+ ### Slim テンプレート
450
+
451
+ Slimテンプレートを使うにはslimライブラリが必要です:
452
+
453
+ # slimを読み込みます
454
+ require 'slim'
455
+
456
+ get '/' do
457
+ slim :index
458
+ end
459
+
460
+ `./views/index.slim`を表示します。
461
+
462
+ ### Creole テンプレート
463
+
464
+ Creoleテンプレートを使うにはcreoleライブラリが必要です:
465
+
466
+ # creoleを読み込みます
467
+ require 'creole'
468
+
469
+ get '/' do
470
+ creole :index
471
+ end
472
+
473
+ `./views/index.creole`を表示します。
474
+
475
+ ### CoffeeScript テンプレート
476
+
477
+ CoffeeScriptテンプレートを表示するにはcoffee-scriptライブラリと\`coffee\`バイナリが必要です:
478
+
479
+ # coffee-scriptを読み込みます
480
+ require 'coffee-script'
481
+
482
+ get '/application.js' do
483
+ coffee :application
484
+ end
485
+
486
+ `./views/application.coffee`を表示します。
487
+
488
+ ### インラインテンプレート
489
+
490
+ get '/' do
491
+ haml '%div.title Hello World'
492
+ end
493
+
494
+ 文字列をテンプレートとして表示します。
495
+
496
+ ### テンプレート内で変数にアクセスする
497
+
498
+ テンプレートはルートハンドラと同じコンテキストの中で評価されます。.
499
+ ルートハンドラでセットされたインスタンス変数は
500
+ テンプレート内で直接使うことができます。
501
+
502
+ get '/:id' do
503
+ @foo = Foo.find(params[:id])
504
+ haml '%h1= @foo.name'
505
+ end
506
+
507
+ ローカル変数を明示的に定義することもできます。
508
+
509
+ get '/:id' do
510
+ foo = Foo.find(params[:id])
511
+ haml '%h1= foo.name', :locals => { :foo => foo }
512
+ end
513
+
514
+ このやり方は他のテンプレート内で部分テンプレートとして表示する時に典型的に使用されます。
515
+
516
+ ### ファイル内テンプレート
517
+
518
+ テンプレートはソースファイルの最後で定義することもできます。
519
+
520
+ require 'rubygems'
521
+ require 'sinatra'
522
+
523
+ get '/' do
524
+ haml :index
525
+ end
526
+
527
+ __END__
528
+
529
+ @@ layout
530
+ %html
531
+ = yield
532
+
533
+ @@ index
534
+ %div.title Hello world!!!!!
535
+
536
+ 注意:
537
+ sinatraをrequireするファイル内で定義されたファイル内テンプレートは自動的に読み込まれます。
538
+ 他のファイルで定義されているテンプレートを使うには
539
+ `enable :inline_templates`を明示的に呼んでください。
540
+
541
+ ### 名前付きテンプレート
542
+
543
+ テンプレートはトップレベルの`template`メソッドで定義することができます。
544
+
545
+ template :layout do
546
+ "%html\n =yield\n"
547
+ end
548
+
549
+ template :index do
550
+ '%div.title Hello World!'
551
+ end
552
+
553
+ get '/' do
554
+ haml :index
555
+ end
556
+
557
+ 「layout」というテンプレートが存在する場合、そのテンプレートファイルは他のテンプレートが
558
+ 表示される度に使用されます。`:layout => false`することでlayoutsを無効にできます。
559
+
560
+ get '/' do
561
+ haml :index, :layout => !request.xhr?
562
+ end
563
+
564
+ ## ヘルパー
565
+
566
+ トップレベルの`helpers`を使用してルートハンドラやテンプレートで使うヘルパメソッドを
567
+ 定義できます。
568
+
569
+ helpers do
570
+ def bar(name)
571
+ "#{name}bar"
572
+ end
573
+ end
574
+
575
+ get '/:name' do
576
+ bar(params[:name])
577
+ end
578
+
579
+ ## フィルタ
580
+
581
+ beforeフィルタはリクエストされたコンテキストを実行する前に評価され、
582
+ リクエストとレスポンスを変更することができます。フィルタ内でセットされた
583
+ インスタンス変数はルーティングとテンプレートで使用できます。
584
+
585
+ before do
586
+ @note = 'Hi!'
587
+ request.path_info = '/foo/bar/baz'
588
+ end
589
+
590
+ get '/foo/*' do
591
+ @note #=> 'Hi!'
592
+ params[:splat] #=> 'bar/baz'
593
+ end
594
+
595
+ afterフィルタは同じコンテキストにあるリクエストの後に評価され、
596
+ 同じくリクエストとレスポンスを変更することができます。
597
+ beforeフィルタとルートで設定されたインスタンス変数は、
598
+ afterフィルタからアクセスすることができます:
599
+
600
+ after do
601
+ puts response.status
602
+ end
603
+
604
+ フィルタにはオプションとしてパターンを渡すことができ、
605
+ この場合はリクエストのパスがパターンにマッチした場合のみフィルタが評価されます:
606
+
607
+ before '/protected/*' do
608
+ authenticate!
609
+ end
610
+
611
+ after '/create/:slug' do |slug|
612
+ session[:last_slug] = slug
613
+ end
614
+
615
+ ## 強制終了
616
+
617
+ ルートかbeforeフィルタ内で直ちに実行を終了する方法:
618
+
619
+ halt
620
+
621
+ ステータスを指定することができます:
622
+
623
+ halt 410
624
+
625
+ body部を指定することもできます …
626
+
627
+ halt 'ここにbodyを書く'
628
+
629
+ ステータスとbody部を指定する …
630
+
631
+ halt 401, '立ち去れ!'
632
+
633
+ ヘッダを指定:
634
+
635
+ halt 402, {'Content-Type' => 'text/plain'}, 'リベンジ'
636
+
637
+ ## パッシング(Passing)
638
+
639
+ ルートは`pass`を使って次のルートに飛ばすことができます:
640
+
641
+ get '/guess/:who' do
642
+ pass unless params[:who] == 'Frank'
643
+ "見つかっちゃった!"
644
+ end
645
+
646
+ get '/guess/*' do
647
+ "はずれです!"
648
+ end
649
+
650
+ ルートブロックからすぐに抜け出し、次にマッチするルートを実行します。
651
+ マッチするルートが見当たらない場合は404が返されます。
652
+
653
+ ## リクエストオブジェクトへのアクセス
654
+
655
+ 受信するリクエストオブジェクトは、\`request\`メソッドを通じてリクエストレベル(フィルタ、ルート、エラーハンドラ)からアクセスすることができます:
656
+
657
+ # アプリケーションが http://example.com/example で動作している場合
658
+ get '/foo' do
659
+ request.body # クライアントによって送信されたリクエストボディ(下記参照)
660
+ request.scheme # "http"
661
+ request.script_name # "/example"
662
+ request.path_info # "/foo"
663
+ request.port # 80
664
+ request.request_method # "GET"
665
+ request.query_string # ""
666
+ request.content_length # request.bodyの長さ
667
+ request.media_type # request.bodyのメディアタイプ
668
+ request.host # "example.com"
669
+ request.get? # true (他の動詞についても同様のメソッドあり)
670
+ request.form_data? # false
671
+ request["SOME_HEADER"] # SOME_HEADERヘッダの値
672
+ request.referer # クライアントのリファラまたは'/'
673
+ request.user_agent # ユーザエージェント (:agent 条件によって使用される)
674
+ request.cookies # ブラウザクッキーのハッシュ
675
+ request.xhr? # Ajaxリクエストかどうか
676
+ request.url # "http://example.com/example/foo"
677
+ request.path # "/example/foo"
678
+ request.ip # クライアントのIPアドレス
679
+ request.secure? # false
680
+ request.env # Rackによって渡された生のenvハッシュ
681
+ end
682
+
683
+ `script_name`や`path_info`などのオプションは次のように利用することもできます:
684
+
685
+ before { request.path_info = "/" }
686
+
687
+ get "/" do
688
+ "全てのリクエストはここに来る"
689
+ end
690
+
691
+ `request.body`はIOまたはStringIOのオブジェクトです:
692
+
693
+ post "/api" do
694
+ request.body.rewind # 既に読まれているときのため
695
+ data = JSON.parse request.body.read
696
+ "Hello #{data['name']}!"
697
+ end
698
+
699
+ ## 設定
700
+
701
+ どの環境でも起動時に1回だけ実行されます。
702
+
703
+ configure do
704
+ ...
705
+ end
706
+
707
+ 環境(RACK\_ENV環境変数)が`:production`に設定されている時だけ実行する方法:
708
+
709
+ configure :production do
710
+ ...
711
+ end
712
+
713
+ 環境が`:production`か`:test`の場合に設定する方法:
714
+
715
+ configure :production, :test do
716
+ ...
717
+ end
718
+
719
+ ## エラーハンドリング
720
+
721
+ エラーハンドラーはルートコンテキストとbeforeフィルタ内で実行します。
722
+ `haml`、`erb`、`halt`などを使うこともできます。
723
+
724
+ ### Not Found
725
+
726
+ `Sinatra::NotFound`が起きた時か レスポンスのステータスコードが
727
+ 404の時に`not_found`ハンドラーが発動します。
728
+
729
+ not_found do
730
+ 'ファイルが存在しません'
731
+ end
732
+
733
+ ### エラー
734
+
735
+ `error`
736
+ ハンドラーはルートブロックかbeforeフィルタ内で例外が発生した時はいつでも発動します。
737
+ 例外オブジェクトはRack変数`sinatra.error`から取得できます。
738
+
739
+ error do
740
+ 'エラーが発生しました。 - ' + env['sinatra.error'].name
741
+ end
742
+
743
+ エラーをカスタマイズする場合は、
744
+
745
+ error MyCustomError do
746
+ 'エラーメッセージ...' + env['sinatra.error'].message
747
+ end
748
+
749
+ と書いておいて,下記のように呼び出します。
750
+
751
+ get '/' do
752
+ raise MyCustomError, '何かがまずかったようです'
753
+ end
754
+
755
+ そうするとこうなります:
756
+
757
+ エラーメッセージ... 何かがまずかったようです
758
+
759
+ あるいは、ステータスコードに対応するエラーハンドラを設定することもできます:
760
+
761
+ error 403 do
762
+ 'Access forbidden'
763
+ end
764
+
765
+ get '/secret' do
766
+ 403
767
+ end
768
+
769
+ 範囲指定もできます:
770
+
771
+ error 400..510 do
772
+ 'Boom'
773
+ end
774
+
775
+ 開発環境として実行している場合、Sinatraは特別な`not_found`と`error`ハンドラーを
776
+ インストールしています。
777
+
778
+ ## MIMEタイプ
779
+
780
+ `send_file`か静的ファイルを使う時、Sinatraが理解でいないMIMEタイプがある場合があります。
781
+ その時は `mime_type` を使ってファイル拡張子毎に登録して下さい。
782
+
783
+ mime_type :foo, 'text/foo'
784
+
785
+ これはcontent\_typeヘルパで利用することができます:
786
+
787
+ content_type :foo
788
+
789
+ ## Rackミドルウェア
790
+
791
+ [SinatraはRack](http://rack.rubyforge.org/)フレームワーク用の
792
+ 最小限の標準インターフェース
793
+ 上で動作しています。Rack中でもアプリケーションデベロッパー
794
+ 向けに一番興味深い機能はミドルウェア(サーバとアプリケーション間に介在し、モニタリング、HTTPリクエストとレスポンス
795
+ の手動操作ができるなど、一般的な機能のいろいろなことを提供するもの)をサポートすることです。
796
+
797
+ Sinatraではトップレベルの`use`
798
+ メソッドを使ってRackにパイプラインを構築します。
799
+
800
+ require 'sinatra'
801
+ require 'my_custom_middleware'
802
+
803
+ use Rack::Lint
804
+ use MyCustomMiddleware
805
+
806
+ get '/hello' do
807
+ 'Hello World'
808
+ end
809
+
810
+ `use`
811
+ [Rack::Builder](http://rack.rubyforge.org/doc/classes/Rack/Builder.html)
812
+ DSLで定義されていることと全て一致します。 例えば `use`
813
+ メソッドはブロック構文のように複数の引数を受け取ることができます。
814
+
815
+ use Rack::Auth::Basic do |username, password|
816
+ username == 'admin' && password == 'secret'
817
+ end
818
+
819
+ Rackはログ、デバッギング、URLルーティング、認証、セッションなどいろいろな機能を備えた標準的ミドルウェアです。
820
+ Sinatraはその多くのコンポーネントを自動で使うよう基本設定されているため、`use`で明示的に指定する必要はありません。
821
+
822
+ ## テスト
823
+
824
+ SinatraでのテストはRack-basedのテストライブラリかフレームワークを使って書くことができます。
825
+ [Rack::Test](http://gitrdoc.com/brynary/rack-test)
826
+ をおすすめします。やり方:
827
+
828
+ require 'my_sinatra_app'
829
+ require 'rack/test'
830
+
831
+ class MyAppTest < Test::Unit::TestCase
832
+ include Rack::Test::Methods
833
+
834
+ def app
835
+ Sinatra::Application
836
+ end
837
+
838
+ def test_my_default
839
+ get '/'
840
+ assert_equal 'Hello World!', last_response.body
841
+ end
842
+
843
+ def test_with_params
844
+ get '/meet', :name => 'Frank'
845
+ assert_equal 'Hello Frank!', last_response.body
846
+ end
847
+
848
+ def test_with_rack_env
849
+ get '/', {}, 'HTTP_USER_AGENT' => 'Songbird'
850
+ assert_equal "あなたはSongbirdを使ってますね!", last_response.body
851
+ end
852
+ end
853
+
854
+ 注意: ビルトインのSinatra::TestモジュールとSinatra::TestHarnessクラスは
855
+ 0.9.2リリース以降、廃止予定になっています。
856
+
857
+ ## Sinatra::Base - ミドルウェア、ライブラリ、 モジュラーアプリ
858
+
859
+ トップレベル(グローバル領域)上でいろいろ定義していくのは軽量アプリならうまくいきますが、
860
+ RackミドルウェアやRails metal、サーバのコンポーネントを含んだシンプルな
861
+ ライブラリやSinatraの拡張プログラムを考慮するような場合はそうとは限りません。
862
+ トップレベルのDSLがネームスペースを汚染したり、設定を変えてしまうこと(例:./publicや./view)がありえます。
863
+ そこでSinatra::Baseの出番です。
864
+
865
+ require 'sinatra/base'
866
+
867
+ class MyApp < Sinatra::Base
868
+ set :sessions, true
869
+ set :foo, 'bar'
870
+
871
+ get '/' do
872
+ 'Hello world!'
873
+ end
874
+ end
875
+
876
+ このMyAppは独立したRackコンポーネントで、RackミドルウェアやRackアプリケーション
877
+ Rails metalとして使用することができます。`config.ru`ファイル内で `use`
878
+ か、または `run`
879
+ でこのクラスを指定するか、ライブラリとしてサーバコンポーネントをコントロールします。
880
+
881
+ MyApp.run! :host => 'localhost', :port => 9090
882
+
883
+ Sinatra::Baseのサブクラスで使えるメソッドはトップレベルのDSLを経由して確実に使うことができます。
884
+ ほとんどのトップレベルで記述されたアプリは、以下の2点を修正することでSinatra::Baseコンポーネントに変えることができます。
885
+
886
+ - `sinatra`の代わりに`sinatra/base`を読み込む
887
+
888
+ (そうしない場合、SinatraのDSLメソッドの全てがメインネームスペースにインポートされます)
889
+
890
+ - ルート、エラーハンドラー、フィルター、オプションをSinatra::Baseのサブクラスに書く
891
+
892
+ `Sinatra::Base`
893
+ はまっさらです。ビルトインサーバを含む、ほとんどのオプションがデフォルト
894
+ で無効になっています。オプション詳細については[Options and
895
+ Configuration](http://sinatra.github.com/configuration.html)
896
+ をご覧下さい。
897
+
898
+ 補足:
899
+ SinatraのトップレベルDSLはシンプルな委譲(delgation)システムで実装されています。
900
+ `Sinatra::Application`クラス(Sinatra::Baseの特別なサブクラス)は、トップレベルに送られる
901
+ :get、 :put、 :post、:delete、 :before、:error、:not\_found、
902
+ :configure、:set messagesのこれら 全てを受け取ります。
903
+ 詳細を閲覧されたい方はこちら(英語): [Sinatra::Delegator
904
+ mixin](http://github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb#L1064)
905
+ [included into the main
906
+ namespace](http://github.com/sinatra/sinatra/blob/master/lib/sinatra/main.rb#L25).
907
+
908
+ ### Sinatraをミドルウェアとして利用する
909
+
910
+ Sinatraは他のRackミドルウェアを利用することができるだけでなく、
911
+ 全てのSinatraアプリケーションは、それ自体ミドルウェアとして別のRackエンドポイントの前に追加することが可能です。
912
+
913
+ このエンドポイントには、別のSinatraアプリケーションまたは他のRackベースのアプリケーション(Rails/Ramaze/Camping/…)が用いられるでしょう。
914
+
915
+ require 'sinatra/base'
916
+
917
+ class LoginScreen < Sinatra::Base
918
+ enable :sessions
919
+
920
+ get('/login') { haml :login }
921
+
922
+ post('/login') do
923
+ if params[:name] = 'admin' and params[:password] = 'admin'
924
+ session['user_name'] = params[:name]
925
+ else
926
+ redirect '/login'
927
+ end
928
+ end
929
+ end
930
+
931
+ class MyApp < Sinatra::Base
932
+ # middleware will run before filters
933
+ use LoginScreen
934
+
935
+ before do
936
+ unless session['user_name']
937
+ halt "Access denied, please <a href='/login'>login</a>."
938
+ end
939
+ end
940
+
941
+ get('/') { "Hello #{session['user_name']}." }
942
+ end
943
+
944
+ ## スコープとバインディング
945
+
946
+ 現在のスコープはどのメソッドや変数が利用可能かを決定します。
947
+
948
+ ### アプリケーション/クラスのスコープ
949
+
950
+ 全てのSinatraアプリケーションはSinatra::Baseのサブクラスに相当します。
951
+ もしトップレベルDSLを利用しているならば(`require 'sinatra'`)このクラスはSinatra::Applicationであり、
952
+ そうでなければ、あなたが明示的に作成したサブクラスです。
953
+ クラスレベルでは\`get\`や\`before\`のようなメソッドを持っています。
954
+ しかし\`request\`オブジェクトや\`session\`には、全てのリクエストのために1つのアプリケーションクラスが存在するためアクセスできません。
955
+
956
+ \`set\`によって作られたオプションはクラスレベルのメソッドです:
957
+
958
+ class MyApp < Sinatra::Base
959
+ # Hey, I'm in the application scope!
960
+ set :foo, 42
961
+ foo # => 42
962
+
963
+ get '/foo' do
964
+ # Hey, I'm no longer in the application scope!
965
+ end
966
+ end
967
+
968
+ 次の場所ではアプリケーションスコープバインディングを持ちます:
969
+
970
+ - アプリケーションのクラス本体
971
+
972
+ - 拡張によって定義されたメソッド
973
+
974
+ - \`helpers\`に渡されたブロック
975
+
976
+ - \`set\`の値として使われるProcまたはブロック
977
+
978
+ このスコープオブジェクト(クラス)は次のように利用できます:
979
+
980
+ - configureブロックに渡されたオブジェクト経由(`configure { |c| ... }`)
981
+
982
+ - リクエストスコープの中での\`settings\`
983
+
984
+ ### リクエスト/インスタンスのスコープ
985
+
986
+ やってくるリクエストごとに、あなたのアプリケーションクラスの新しいインスタンスが作成され、全てのハンドラブロックがそのスコープで実行されます。
987
+ このスコープの内側からは\`request\`や\`session\`オブジェクトにアクセスすることができ、\`erb\`や\`haml\`のような表示メソッドを呼び出すことができます。
988
+ リクエストスコープの内側からは、\`settings\`ヘルパによってアプリケーションスコープにアクセスすることができます。
989
+
990
+ class MyApp < Sinatra::Base
991
+ # Hey, I'm in the application scope!
992
+ get '/define_route/:name' do
993
+ # Request scope for '/define_route/:name'
994
+ @value = 42
995
+
996
+ settings.get("/#{params[:name]}") do
997
+ # Request scope for "/#{params[:name]}"
998
+ @value # => nil (not the same request)
999
+ end
1000
+
1001
+ "Route defined!"
1002
+ end
1003
+ end
1004
+
1005
+ 次の場所ではリクエストスコープバインディングを持ちます:
1006
+
1007
+ - get/head/post/put/delete ブロック
1008
+
1009
+ - before/after フィルタ
1010
+
1011
+ - helper メソッド
1012
+
1013
+ - テンプレート/ビュー
1014
+
1015
+ ### デリゲートスコープ
1016
+
1017
+ デリゲートスコープは、単にクラススコープにメソッドを転送します。
1018
+ しかしながら、クラスのバインディングを持っていないため、クラススコープと全く同じふるまいをするわけではありません:
1019
+ 委譲すると明示的に示されたメソッドのみが利用可能であり、またクラススコープと変数/状態を共有することはできません(注:
1020
+ 異なった\`self\`を持っています)。
1021
+ `Sinatra::Delegator.delegate :method_name`を呼び出すことによってデリゲートするメソッドを明示的に追加することができます。
1022
+
1023
+ 次の場所ではデリゲートスコープを持ちます:
1024
+
1025
+ - もし`require "sinatra"`しているならば、トップレベルバインディング
1026
+
1027
+ - \`Sinatra::Delegator\` mixinでextendされたオブジェクト
1028
+
1029
+ コードをご覧ください: ここでは [Sinatra::Delegator
1030
+ mixin](http://github.com/sinatra/sinatra/blob/ceac46f0bc129a6e994a06100aa854f606fe5992/lib/sinatra/base.rb#L1128)
1031
+ は[main
1032
+ 名前空間にincludeされています](http://github.com/sinatra/sinatra/blob/ceac46f0bc129a6e994a06100aa854f606fe5992/lib/sinatra/main.rb#L28).
1033
+
1034
+ ## コマンドライン
1035
+
1036
+ Sinatraアプリケーションは直接実行できます。
1037
+
1038
+ ruby myapp.rb [-h] [-x] [-e ENVIRONMENT] [-p PORT] [-o HOST] [-s HANDLER]
1039
+
1040
+ オプション:
1041
+
1042
+ -h # ヘルプ
1043
+ -p # ポート指定(デフォルトは4567)
1044
+ -o # ホスト指定(デフォルトは0.0.0.0)
1045
+ -e # 環境を指定 (デフォルトはdevelopment)
1046
+ -s # rackserver/handlerを指定 (デフォルトはthin)
1047
+ -x # mutex lockを付ける (デフォルトはoff)
1048
+
1049
+ ## 最新開発版について
1050
+
1051
+ Sinatraの開発版を使いたい場合は、ローカルに開発版を落として、
1052
+ `LOAD_PATH`の`sinatra/lib`ディレクトリを指定して実行して下さい。
1053
+
1054
+ cd myapp
1055
+ git clone git://github.com/sinatra/sinatra.git
1056
+ ruby -Isinatra/lib myapp.rb
1057
+
1058
+ `sinatra/lib`ディレクトリをアプリケーションの`LOAD_PATH`に追加する方法もあります。
1059
+
1060
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/sinatra/lib'
1061
+ require 'rubygems'
1062
+ require 'sinatra'
1063
+
1064
+ get '/about' do
1065
+ "今使ってるバージョンは" + Sinatra::VERSION
1066
+ end
1067
+
1068
+ Sinatraのソースを更新する方法:
1069
+
1070
+ cd myproject/sinatra
1071
+ git pull
1072
+
1073
+ ## その他
1074
+
1075
+ 日本語サイト
1076
+
1077
+ - [Greenbear Laboratory
1078
+ Rack日本語マニュアル](http://mono.kmc.gr.jp/~yhara/w/?RackReferenceJa)
1079
+ - Rackの日本語マニュアル
1080
+
1081
+ 英語サイト
1082
+
1083
+ - [プロジェクトサイト](http://sinatra.github.com/) - ドキュメント、
1084
+ ニュース、他のリソースへのリンクがあります。
1085
+
1086
+ - [プロジェクトに参加(貢献)する](http://sinatra.github.com/contributing.html)
1087
+ - バグレポート パッチの送信、サポートなど
1088
+
1089
+ - [Issue tracker](http://github.com/sinatra/sinatra/issues) -
1090
+ チケット管理とリリース計画
1091
+
1092
+ - [Twitter](http://twitter.com/sinatra)
1093
+
1094
+ - [メーリングリスト](http://groups.google.com/group/sinatrarb)
1095
+
1096
+ - [IRC: \#sinatra](irc://chat.freenode.net/#sinatra) on
1097
+ [freenode.net](http://freenode.net)