sinatra 2.2.4 → 3.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/README.ja.md DELETED
@@ -1,2844 +0,0 @@
1
- # Sinatra
2
-
3
- *注)
4
- 本文書は英語から翻訳したものであり、その内容が最新でない場合もあります。最新の情報はオリジナルの英語版を参照してください。*
5
-
6
- Sinatraは最小の労力でRubyによるWebアプリケーションを手早く作るための[DSL](https://ja.wikipedia.org/wiki/メインページドメイン固有言語)です。
7
-
8
- ```ruby
9
- # myapp.rb
10
- require 'sinatra'
11
-
12
- get '/' do
13
- 'Hello world!'
14
- end
15
- ```
16
-
17
- gemをインストールし、
18
-
19
- ```shell
20
- gem install sinatra
21
- ```
22
-
23
- 次のように実行します。
24
-
25
- ```shell
26
- ruby myapp.rb
27
- ```
28
-
29
- [http://localhost:4567](http://localhost:4567) を開きます。
30
-
31
- コードを変更しても、サーバを再起動しないと変更が有効になりません。
32
- コードを変更するたびにサーバを再起動するか、[sinatra/reloader](http://www.sinatrarb.com/contrib/reloader)を使ってください。
33
-
34
- PumaがあればSinatraはこれを利用するので、`gem install puma`することをお薦めします。
35
-
36
- ## 目次
37
-
38
- * [Sinatra](#sinatra)
39
- * [目次](#目次)
40
- * [ルーティング(Routes)](#ルーティングroutes)
41
- * [条件(Conditions)](#条件conditions)
42
- * [戻り値(Return Values)](#戻り値return-values)
43
- * [カスタムルーティングマッチャー(Custom Route Matchers)](#カスタムルーティングマッチャーcustom-route-matchers)
44
- * [静的ファイル(Static Files)](#静的ファイルstatic-files)
45
- * [ビュー / テンプレート(Views / Templates)](#ビュー--テンプレートviews--templates)
46
- * [リテラルテンプレート(Literal Templates)](#リテラルテンプレートliteral-templates)
47
- * [利用可能なテンプレート言語](#利用可能なテンプレート言語)
48
- * [Haml テンプレート](#haml-テンプレート)
49
- * [Erb テンプレート](#erb-テンプレート)
50
- * [Builder テンプレート](#builder-テンプレート)
51
- * [Nokogiri テンプレート](#nokogiri-テンプレート)
52
- * [Sass テンプレート](#sass-テンプレート)
53
- * [SCSS テンプレート](#scss-テンプレート)
54
- * [Less テンプレート](#less-テンプレート)
55
- * [Liquid テンプレート](#liquid-テンプレート)
56
- * [Markdown テンプレート](#markdown-テンプレート)
57
- * [Textile テンプレート](#textile-テンプレート)
58
- * [RDoc テンプレート](#rdoc-テンプレート)
59
- * [AsciiDoc テンプレート](#asciidoc-テンプレート)
60
- * [Radius テンプレート](#radius-テンプレート)
61
- * [Markaby テンプレート](#markaby-テンプレート)
62
- * [RABL テンプレート](#rabl-テンプレート)
63
- * [Slim テンプレート](#slim-テンプレート)
64
- * [Creole テンプレート](#creole-テンプレート)
65
- * [MediaWiki テンプレート](#mediawiki-テンプレート)
66
- * [CoffeeScript テンプレート](#coffeescript-テンプレート)
67
- * [Stylus テンプレート](#stylus-テンプレート)
68
- * [Yajl テンプレート](#yajl-テンプレート)
69
- * [WLang テンプレート](#wlang-テンプレート)
70
- * [テンプレート内での変数へのアクセス](#テンプレート内での変数へのアクセス)
71
- * [`yield`を伴うテンプレートとネストしたレイアウト](#yieldを伴うテンプレートとネストしたレイアウト)
72
- * [インラインテンプレート(Inline Templates)](#インラインテンプレートinline-templates)
73
- * [名前付きテンプレート(Named Templates)](#名前付きテンプレートnamed-templates)
74
- * [ファイル拡張子の関連付け](#ファイル拡張子の関連付け)
75
- * [オリジナルテンプレートエンジンの追加](#オリジナルテンプレートエンジンの追加)
76
- * [カスタムロジックを使用したテンプレートの探索](#カスタムロジックを使用したテンプレートの探索)
77
- * [フィルタ(Filters)](#フィルタfilters)
78
- * [ヘルパー(Helpers)](#ヘルパーhelpers)
79
- * [セッションの使用](#セッションの使用)
80
- * [セッションミドルウェアの選択](#セッションミドルウェアの選択)
81
- * [停止(Halting)](#停止halting)
82
- * [パッシング(Passing)](#パッシングpassing)
83
- * [別ルーティングの誘発](#別ルーティングの誘発)
84
- * [ボディ、ステータスコードおよびヘッダの設定](#ボディステータスコードおよびヘッダの設定)
85
- * [ストリーミングレスポンス(Streaming Responses)](#ストリーミングレスポンスstreaming-responses)
86
- * [ロギング(Logging)](#ロギングlogging)
87
- * [MIMEタイプ(Mime Types)](#mimeタイプmime-types)
88
- * [URLの生成](#urlの生成)
89
- * [ブラウザリダイレクト(Browser Redirect)](#ブラウザリダイレクトbrowser-redirect)
90
- * [キャッシュ制御(Cache Control)](#キャッシュ制御cache-control)
91
- * [ファイルの送信](#ファイルの送信)
92
- * [リクエストオブジェクトへのアクセス](#リクエストオブジェクトへのアクセス)
93
- * [アタッチメント(Attachments)](#アタッチメントattachments)
94
- * [日付と時刻の取り扱い](#日付と時刻の取り扱い)
95
- * [テンプレートファイルの探索](#テンプレートファイルの探索)
96
- * [コンフィギュレーション(Configuration)](#コンフィギュレーションconfiguration)
97
- * [攻撃防御に対する設定](#攻撃防御に対する設定)
98
- * [利用可能な設定](#利用可能な設定)
99
- * [環境設定(Environments)](#環境設定environments)
100
- * [エラーハンドリング(Error Handling)](#エラーハンドリングerror-handling)
101
- * [Not Found](#not-found)
102
- * [エラー(Error)](#エラーerror)
103
- * [Rackミドルウェア(Rack Middleware)](#rackミドルウェアrack-middleware)
104
- * [テスト(Testing)](#テストtesting)
105
- * [Sinatra::Base - ミドルウェア、ライブラリおよびモジュラーアプリ](#sinatrabase---ミドルウェアライブラリおよびモジュラーアプリ)
106
- * [モジュラースタイル vs クラッシックスタイル](#モジュラースタイル-vs-クラッシックスタイル)
107
- * [モジュラーアプリケーションの提供](#モジュラーアプリケーションの提供)
108
- * [config.ruを用いたクラッシックスタイルアプリケーションの使用](#configruを用いたクラッシックスタイルアプリケーションの使用)
109
- * [config.ruはいつ使うのか?](#configruはいつ使うのか)
110
- * [Sinatraのミドルウェアとしての利用](#sinatraのミドルウェアとしての利用)
111
- * [動的なアプリケーションの生成](#動的なアプリケーションの生成)
112
- * [スコープとバインディング(Scopes and Binding)](#スコープとバインディングscopes-and-binding)
113
- * [アプリケーション/クラスのスコープ](#アプリケーションクラスのスコープ)
114
- * [リクエスト/インスタンスのスコープ](#リクエストインスタンスのスコープ)
115
- * [デリゲートスコープ](#デリゲートスコープ)
116
- * [コマンドライン](#コマンドライン)
117
- * [マルチスレッド](#マルチスレッド)
118
- * [必要環境](#必要環境)
119
- * [最新開発版](#最新開発版)
120
- * [Bundlerを使う場合](#bundlerを使う場合)
121
- * [直接組み込む場合](#直接組み込む場合)
122
- * [グローバル環境にインストールする場合](#グローバル環境にインストールする場合)
123
- * [バージョニング(Versioning)](#バージョニングversioning)
124
- * [参考文献](#参考文献)
125
-
126
- ## ルーティング(Routes)
127
-
128
- Sinatraでは、ルーティングはHTTPメソッドとURLマッチングパターンがペアになっています。
129
- ルーティングはブロックに結び付けられています。
130
-
131
- ```ruby
132
- get '/' do
133
- .. 何か見せる ..
134
- end
135
-
136
- post '/' do
137
- .. 何か生成する ..
138
- end
139
-
140
- put '/' do
141
- .. 何か更新する ..
142
- end
143
-
144
- patch '/' do
145
- .. 何か修正する ..
146
- end
147
-
148
- delete '/' do
149
- .. 何か削除する ..
150
- end
151
-
152
- options '/' do
153
- .. 何か満たす ..
154
- end
155
-
156
- link '/' do
157
- .. 何かリンクを張る ..
158
- end
159
-
160
- unlink '/' do
161
- .. 何かアンリンクする ..
162
- end
163
- ```
164
-
165
- ルーティングは定義された順番にマッチします。
166
- リクエストに最初にマッチしたルーティングが呼び出されます。
167
-
168
- トレイリングスラッシュを付けたルートは、そうでないルートと異なったものになります。
169
-
170
- ```ruby
171
- get '/foo' do
172
- # Does not match "GET /foo/"
173
- end
174
- ```
175
-
176
- ルーティングのパターンは名前付きパラメータを含むことができ、
177
- `params`ハッシュで取得できます。
178
-
179
- ```ruby
180
- get '/hello/:name' do
181
- # "GET /hello/foo" と "GET /hello/bar" にマッチ
182
- # params['name'] は 'foo' か 'bar'
183
- "Hello #{params['name']}!"
184
- end
185
- ```
186
-
187
- また、ブロックパラメータで名前付きパラメータにアクセスすることもできます。
188
-
189
- ```ruby
190
- get '/hello/:name' do |n|
191
- # "GET /hello/foo" と "GET /hello/bar" にマッチ
192
- # params['name'] は 'foo' か 'bar'
193
- # n が params['name'] を保持
194
- "Hello #{n}!"
195
- end
196
- ```
197
-
198
- ルーティングパターンはアスタリスク(すなわちワイルドカード)を含むこともでき、
199
- `params['splat']` で取得できます。
200
-
201
- ```ruby
202
- get '/say/*/to/*' do
203
- # /say/hello/to/world にマッチ
204
- params['splat'] # => ["hello", "world"]
205
- end
206
-
207
- get '/download/*.*' do
208
- # /download/path/to/file.xml にマッチ
209
- params['splat'] # => ["path/to/file", "xml"]
210
- end
211
- ```
212
-
213
- ここで、ブロックパラメータを使うこともできます。
214
-
215
- ```ruby
216
- get '/download/*.*' do |path, ext|
217
- [path, ext] # => ["path/to/file", "xml"]
218
- end
219
- ```
220
-
221
- ルーティングを正規表現にマッチさせることもできます。
222
-
223
- ```ruby
224
- get /\/hello\/([\w]+)/ do
225
- "Hello, #{params['captures'].first}!"
226
- end
227
- ```
228
-
229
- ここでも、ブロックパラメータが使えます。
230
-
231
- ```ruby
232
- get %r{/hello/([\w]+)} do |c|
233
- "Hello, #{c}!"
234
- end
235
- ```
236
-
237
- ルーティングパターンは、オプショナルパラメータを取ることもできます。
238
-
239
- ```ruby
240
- get '/posts/:format?' do
241
- # "GET /posts/" と "GET /posts/json", "GET /posts/xml" の拡張子などにマッチ
242
- end
243
- ```
244
-
245
- ところで、ディレクトリトラバーサル攻撃防御設定を無効にしないと(下記参照)、
246
- ルーティングにマッチする前にリクエストパスが修正される可能性があります。
247
-
248
- ## 条件(Conditions)
249
-
250
- ルーティングにはユーザエージェントのようなさまざまな条件を含めることができます。
251
-
252
- ```ruby
253
- get '/foo', :agent => /Songbird (\d\.\d)[\d\/]*?/ do
254
- "Songbirdのバージョン #{params['agent'][0]}を使ってます。"
255
- end
256
-
257
- get '/foo' do
258
- # Songbird以外のブラウザにマッチ
259
- end
260
- ```
261
-
262
- ほかに`host_name`と`provides`条件が利用可能です。
263
-
264
- ```ruby
265
- get '/', :host_name => /^admin\./ do
266
- "Adminエリアです。アクセスを拒否します!"
267
- end
268
-
269
- get '/', :provides => 'html' do
270
- haml :index
271
- end
272
-
273
- get '/', :provides => ['rss', 'atom', 'xml'] do
274
- builder :feed
275
- end
276
- ```
277
-
278
- 独自の条件を定義することも簡単にできます。
279
-
280
- ```ruby
281
- set(:probability) { |value| condition { rand <= value } }
282
-
283
- get '/win_a_car', :probability => 0.1 do
284
- "あなたの勝ちです!"
285
- end
286
-
287
- get '/win_a_car' do
288
- "残念、あなたの負けです。"
289
- end
290
- ```
291
-
292
- 複数の値を取る条件には、アスタリスクを使います。
293
-
294
- ```ruby
295
- set(:auth) do |*roles| # <- ここでアスタリスクを使う
296
- condition do
297
- unless logged_in? && roles.any? {|role| current_user.in_role? role }
298
- redirect "/login/", 303
299
- end
300
- end
301
- end
302
-
303
- get "/my/account/", :auth => [:user, :admin] do
304
- "アカウントの詳細"
305
- end
306
-
307
- get "/only/admin/", :auth => :admin do
308
- "ここは管理者だけ!"
309
- end
310
- ```
311
-
312
- ## 戻り値(Return Values)
313
-
314
- ルーティングブロックの戻り値は、HTTPクライアントまたはRackスタックでの次のミドルウェアに渡されるレスポンスボディを決定します。
315
-
316
- これは大抵の場合、上の例のように文字列ですが、それ以外の値も使用することができます。
317
-
318
- Rackレスポンス、Rackボディオブジェクト、HTTPステータスコードのいずれかとして妥当なオブジェクトであればどのようなオブジェクトでも返すことができます。
319
-
320
- * 3つの要素を含む配列:
321
- `[ステータス(Integer), ヘッダ(Hash), レスポンスボディ(#eachに応答する)]`
322
- * 2つの要素を含む配列:
323
- `[ステータス(Integer), レスポンスボディ(#eachに応答する)]`
324
- * `#each`に応答するオブジェクト。通常はそのまま何も返さないが、
325
- 与えられたブロックに文字列を渡す。
326
- * ステータスコードを表現する整数(Integer)
327
-
328
- これにより、例えばストリーミングを簡単に実装することができます。
329
-
330
- ```ruby
331
- class Stream
332
- def each
333
- 100.times { |i| yield "#{i}\n" }
334
- end
335
- end
336
-
337
- get('/') { Stream.new }
338
- ```
339
-
340
- 後述する`stream`ヘルパーメソッドを使って、定型パターンを減らしつつストリーミングロジックをルーティングに埋め込むこともできます。
341
-
342
- ## カスタムルーティングマッチャー(Custom Route Matchers)
343
-
344
- 先述のようにSinatraはルーティングマッチャーとして、文字列パターンと正規表現を使うことをビルトインでサポートしています。しかしこれに留まらず、独自のマッチャーを簡単に定義することもできるのです。
345
-
346
- ```ruby
347
- class AllButPattern
348
- Match = Struct.new(:captures)
349
-
350
- def initialize(except)
351
- @except = except
352
- @captures = Match.new([])
353
- end
354
-
355
- def match(str)
356
- @captures unless @except === str
357
- end
358
- end
359
-
360
- def all_but(pattern)
361
- AllButPattern.new(pattern)
362
- end
363
-
364
- get all_but("/index") do
365
- # ...
366
- end
367
- ```
368
-
369
- ノート: この例はオーバースペックであり、以下のようにも書くことができます。
370
-
371
- ```ruby
372
- get // do
373
- pass if request.path_info == "/index"
374
- # ...
375
- end
376
- ```
377
-
378
- または、否定先読みを使って:
379
-
380
- ```ruby
381
- get %r{(?!/index)} do
382
- # ...
383
- end
384
- ```
385
-
386
- ## 静的ファイル(Static Files)
387
-
388
- 静的ファイルは`./public`ディレクトリから配信されます。
389
- `:public_folder`オプションを指定することで別の場所を指定することができます。
390
-
391
- ```ruby
392
- set :public_folder, __dir__ + '/static'
393
- ```
394
-
395
- ノート: この静的ファイル用のディレクトリ名はURL中に含まれません。
396
- 例えば、`./public/css/style.css`は`http://example.com/css/style.css`でアクセスできます。
397
-
398
- `Cache-Control`の設定をヘッダーへ追加するには`:static_cache_control`の設定(下記参照)を加えてください。
399
-
400
- ## ビュー / テンプレート(Views / Templates)
401
-
402
- 各テンプレート言語はそれ自身のレンダリングメソッドを通して展開されます。それらのメソッドは単に文字列を返します。
403
-
404
- ```ruby
405
- get '/' do
406
- erb :index
407
- end
408
- ```
409
-
410
- これは、`views/index.erb`をレンダリングします。
411
-
412
- テンプレート名を渡す代わりに、直接そのテンプレートの中身を渡すこともできます。
413
-
414
- ```ruby
415
- get '/' do
416
- code = "<%= Time.now %>"
417
- erb code
418
- end
419
- ```
420
-
421
- テンプレートのレイアウトは第2引数のハッシュ形式のオプションをもとに表示されます。
422
-
423
- ```ruby
424
- get '/' do
425
- erb :index, :layout => :post
426
- end
427
- ```
428
-
429
- これは、`views/post.erb`内に埋め込まれた`views/index.erb`をレンダリングします(デフォルトは`views/layout.erb`があればそれになります)。
430
-
431
- Sinatraが理解できないオプションは、テンプレートエンジンに渡されることになります。
432
-
433
- ```ruby
434
- get '/' do
435
- haml :index, :format => :html5
436
- end
437
- ```
438
-
439
- テンプレート言語ごとにオプションをセットすることもできます。
440
-
441
- ```ruby
442
- set :haml, :format => :html5
443
-
444
- get '/' do
445
- haml :index
446
- end
447
- ```
448
-
449
- レンダリングメソッドに渡されたオプションは`set`で設定されたオプションを上書きします。
450
-
451
- 利用可能なオプション:
452
-
453
- <dl>
454
- <dt>locals</dt>
455
- <dd>
456
- ドキュメントに渡されるローカルのリスト。パーシャルに便利。
457
- 例: <tt>erb "<%= foo %>", :locals => {:foo => "bar"}</tt>
458
- </dd>
459
-
460
- <dt>default_encoding</dt>
461
- <dd>
462
- 文字エンコーディングが確実でない場合に指定。デフォルトは、<tt>settings.default_encoding</tt>。
463
- </dd>
464
-
465
- <dt>views</dt>
466
- <dd>
467
- テンプレートを読み出すビューのディレクトリ。デフォルトは、<tt>settings.views</tt>。
468
- </dd>
469
-
470
- <dt>layout</dt>
471
- <dd>
472
- レイアウトを使うかの指定(<tt>true</tt> または <tt>false</tt>)。値がシンボルの場合は、使用するテンプレートが指定される。例: <tt>erb :index, :layout => !request.xhr?</tt>
473
- </dd>
474
-
475
- <dt>content_type</dt>
476
- <dd>
477
- テンプレートが生成するContent-Type。デフォルトはテンプレート言語ごとに異なる。
478
- </dd>
479
-
480
- <dt>scope</dt>
481
- <dd>
482
- テンプレートをレンダリングするときのスコープ。デフォルトは、アプリケーションのインスタンス。これを変更した場合、インスタンス変数およびヘルパーメソッドが利用できなくなる。
483
- </dd>
484
-
485
- <dt>layout_engine</dt>
486
- <dd>
487
- レイアウトをレンダリングするために使用するテンプレートエンジン。レイアウトをサポートしない言語で有用。デフォルトはテンプレートに使われるエンジン。例: <tt>set :rdoc, :layout_engine => :erb</tt>
488
- </dd>
489
-
490
- <dt>layout_options</dt>
491
- <dd>
492
- レイアウトをレンダリングするときだけに使う特別なオプション。例:
493
- <tt>set :rdoc, :layout_options => { :views => 'views/layouts' }</tt>
494
- </dd>
495
- </dl>
496
-
497
- テンプレートは`./views`ディレクトリ下に配置されています。
498
- 他のディレクトリを使用する場合の例:
499
-
500
- ```ruby
501
- set :views, settings.root + '/templates'
502
- ```
503
-
504
- テンプレートの参照は、テンプレートがサブディレクトリ内にある場合でも常にシンボルで指定することを覚えておいてください。
505
- (これは`:'subdir/template'`または`'subdir/template'.to_sym`のように指定することを意味します。)
506
- レンダリングメソッドにシンボルではなく文字列を渡してしまうと、そのまま文字列として出力してしまいます。
507
-
508
- ### リテラルテンプレート(Literal Templates)
509
-
510
- ```ruby
511
- get '/' do
512
- haml '%div.title Hello World'
513
- end
514
- ```
515
-
516
- これはテンプレート文字列をレンダリングしています。
517
- テンプレート文字列に関連するファイルパスや行数を`:path`や`:line`オプションで指定することで、バックトレースを明確にすることができます。
518
-
519
- ```ruby
520
- get '/' do
521
- haml '%div.title Hello World', :path => 'examples/file.haml', :line => 3
522
- end
523
- ```
524
-
525
- ### 利用可能なテンプレート言語
526
-
527
- いくつかの言語には複数の実装があります。使用する(そしてスレッドセーフにする)実装を指定するには、それを最初にrequireしてください。
528
-
529
- ```ruby
530
- require 'rdiscount' # または require 'bluecloth'
531
- get('/') { markdown :index }
532
- ```
533
-
534
- #### Haml テンプレート
535
-
536
- <table>
537
- <tr>
538
- <td>依存</td>
539
- <td><a href="http://haml.info/" title="haml">haml</a></td>
540
- </tr>
541
- <tr>
542
- <td>ファイル拡張子</td>
543
- <td><tt>.haml</tt></td>
544
- </tr>
545
- <tr>
546
- <td>例</td>
547
- <td><tt>haml :index, :format => :html5</tt></td>
548
- </tr>
549
- </table>
550
-
551
- #### Erb テンプレート
552
-
553
- <table>
554
- <tr>
555
- <td>依存</td>
556
- <td>
557
- <a href="https://github.com/jeremyevans/erubi" title="erubi">erubi</a>
558
- または <a href="http://www.kuwata-lab.com/erubis/" title="erubis">erubis</a>
559
- または erb (Rubyに同梱)
560
- </td>
561
- </tr>
562
- <tr>
563
- <td>ファイル拡張子</td>
564
- <td><tt>.erb</tt>, <tt>.rhtml</tt> または <tt>.erubi</tt> (Erubiだけ) または<tt>.erubis</tt> (Erubisだけ)</td>
565
- </tr>
566
- <tr>
567
- <td>例</td>
568
- <td><tt>erb :index</tt></td>
569
- </tr>
570
- </table>
571
-
572
- #### Builder テンプレート
573
-
574
- <table>
575
- <tr>
576
- <td>依存</td>
577
- <td>
578
- <a href="https://github.com/jimweirich/builder" title="builder">builder</a>
579
- </td>
580
- </tr>
581
- <tr>
582
- <td>ファイル拡張子</td>
583
- <td><tt>.builder</tt></td>
584
- </tr>
585
- <tr>
586
- <td>例</td>
587
- <td><tt>builder { |xml| xml.em "hi" }</tt></td>
588
- </tr>
589
- </table>
590
-
591
- インラインテンプレート用にブロックを取ることもできます(例を参照)。
592
-
593
- #### Nokogiri テンプレート
594
-
595
- <table>
596
- <tr>
597
- <td>依存</td>
598
- <td><a href="http://www.nokogiri.org/" title="nokogiri">nokogiri</a></td>
599
- </tr>
600
- <tr>
601
- <td>ファイル拡張子</td>
602
- <td><tt>.nokogiri</tt></td>
603
- </tr>
604
- <tr>
605
- <td>例</td>
606
- <td><tt>nokogiri { |xml| xml.em "hi" }</tt></td>
607
- </tr>
608
- </table>
609
-
610
- インラインテンプレート用にブロックを取ることもできます(例を参照)。
611
-
612
- #### Sass テンプレート
613
-
614
- <table>
615
- <tr>
616
- <td>依存</td>
617
- <td><a href="https://sass-lang.com/" title="sass">sass</a></td>
618
- </tr>
619
- <tr>
620
- <td>ファイル拡張子</td>
621
- <td><tt>.sass</tt></td>
622
- </tr>
623
- <tr>
624
- <td>例</td>
625
- <td><tt>sass :stylesheet, :style => :expanded</tt></td>
626
- </tr>
627
- </table>
628
-
629
- #### Scss テンプレート
630
-
631
- <table>
632
- <tr>
633
- <td>依存</td>
634
- <td><a href="https://sass-lang.com/" title="sass">sass</a></td>
635
- </tr>
636
- <tr>
637
- <td>ファイル拡張子</td>
638
- <td><tt>.scss</tt></td>
639
- </tr>
640
- <tr>
641
- <td>例</td>
642
- <td><tt>scss :stylesheet, :style => :expanded</tt></td>
643
- </tr>
644
- </table>
645
-
646
- #### Less テンプレート
647
-
648
- <table>
649
- <tr>
650
- <td>依存</td>
651
- <td><a href="http://lesscss.org/" title="less">less</a></td>
652
- </tr>
653
- <tr>
654
- <td>ファイル拡張子</td>
655
- <td><tt>.less</tt></td>
656
- </tr>
657
- <tr>
658
- <td>例</td>
659
- <td><tt>less :stylesheet</tt></td>
660
- </tr>
661
- </table>
662
-
663
- #### Liquid テンプレート
664
-
665
- <table>
666
- <tr>
667
- <td>依存</td>
668
- <td><a href="https://shopify.github.io/liquid/" title="liquid">liquid</a></td>
669
- </tr>
670
- <tr>
671
- <td>ファイル拡張子</td>
672
- <td><tt>.liquid</tt></td>
673
- </tr>
674
- <tr>
675
- <td>例</td>
676
- <td><tt>liquid :index, :locals => { :key => 'value' }</tt></td>
677
- </tr>
678
- </table>
679
-
680
- LiquidテンプレートからRubyのメソッド(`yield`を除く)を呼び出すことができないため、ほぼ全ての場合にlocalsを指定する必要があるでしょう。
681
-
682
- #### Markdown テンプレート
683
-
684
- <table>
685
- <tr>
686
- <td>依存</td>
687
- <td>
688
- 次の何れか:
689
- <a href="https://github.com/davidfstr/rdiscount" title="RDiscount">RDiscount</a>,
690
- <a href="https://github.com/vmg/redcarpet" title="RedCarpet">RedCarpet</a>,
691
- <a href="https://github.com/ged/bluecloth" title="bluecloth">BlueCloth</a>,
692
- <a href="https://kramdown.gettalong.org/" title="kramdown">kramdown</a>,
693
- <a href="https://github.com/bhollis/maruku" title="maruku">maruku</a>
694
- </td>
695
- </tr>
696
- <tr>
697
- <td>ファイル拡張子</td>
698
- <td><tt>.markdown</tt>, <tt>.mkd</tt> and <tt>.md</tt></td>
699
- </tr>
700
- <tr>
701
- <td>例</td>
702
- <td><tt>markdown :index, :layout_engine => :erb</tt></td>
703
- </tr>
704
- </table>
705
-
706
- Markdownからメソッドを呼び出すことも、localsに変数を渡すこともできません。
707
- それゆえ、他のレンダリングエンジンとの組み合わせで使うのが普通です。
708
-
709
- ```ruby
710
- erb :overview, :locals => { :text => markdown(:introduction) }
711
- ```
712
-
713
- ノート: 他のテンプレート内で`markdown`メソッドを呼び出せます。
714
-
715
- ```ruby
716
- %h1 Hello From Haml!
717
- %p= markdown(:greetings)
718
- ```
719
-
720
- MarkdownからはRubyを呼ぶことができないので、Markdownで書かれたレイアウトを使うことはできません。しかしながら、`:layout_engine`オプションを渡すことでテンプレートのものとは異なるレンダリングエンジンをレイアウトのために使うことができます。
721
-
722
- #### Textile テンプレート
723
-
724
- <table>
725
- <tr>
726
- <td>依存</td>
727
- <td><a href="http://redcloth.org/" title="RedCloth">RedCloth</a></td>
728
- </tr>
729
- <tr>
730
- <td>ファイル拡張子</td>
731
- <td><tt>.textile</tt></td>
732
- </tr>
733
- <tr>
734
- <td>例</td>
735
- <td><tt>textile :index, :layout_engine => :erb</tt></td>
736
- </tr>
737
- </table>
738
-
739
- Textileからメソッドを呼び出すことも、localsに変数を渡すこともできません。
740
- それゆえ、他のレンダリングエンジンとの組み合わせで使うのが普通です。
741
-
742
- ```ruby
743
- erb :overview, :locals => { :text => textile(:introduction) }
744
- ```
745
-
746
- ノート: 他のテンプレート内で`textile`メソッドを呼び出せます。
747
-
748
- ```ruby
749
- %h1 Hello From Haml!
750
- %p= textile(:greetings)
751
- ```
752
-
753
- TextileからはRubyを呼ぶことができないので、Textileで書かれたレイアウトを使うことはできません。しかしながら、`:layout_engine`オプションを渡すことでテンプレートのものとは異なるレンダリングエンジンをレイアウトのために使うことができます。
754
-
755
- #### RDoc テンプレート
756
-
757
- <table>
758
- <tr>
759
- <td>依存</td>
760
- <td><a href="http://rdoc.sourceforge.net/" title="RDoc">RDoc</a></td>
761
- </tr>
762
- <tr>
763
- <td>ファイル拡張子</td>
764
- <td><tt>.rdoc</tt></td>
765
- </tr>
766
- <tr>
767
- <td>例</td>
768
- <td><tt>rdoc :README, :layout_engine => :erb</tt></td>
769
- </tr>
770
- </table>
771
-
772
- RDocからメソッドを呼び出すことも、localsに変数を渡すこともできません。
773
- それゆえ、他のレンダリングエンジンとの組み合わせで使うのが普通です。
774
-
775
- ```ruby
776
- erb :overview, :locals => { :text => rdoc(:introduction) }
777
- ```
778
-
779
- ノート: 他のテンプレート内で`rdoc`メソッドを呼び出せます。
780
-
781
- ```ruby
782
- %h1 Hello From Haml!
783
- %p= rdoc(:greetings)
784
- ```
785
-
786
- RDocからはRubyを呼ぶことができないので、RDocで書かれたレイアウトを使うことはできません。しかしながら、`:layout_engine`オプションを渡すことでテンプレートのものとは異なるレンダリングエンジンをレイアウトのために使うことができます。
787
-
788
- #### AsciiDoc テンプレート
789
-
790
- <table>
791
- <tr>
792
- <td>依存</td>
793
- <td><a href="https://asciidoctor.org/" title="Asciidoctor">Asciidoctor</a></td>
794
- </tr>
795
- <tr>
796
- <td>ファイル拡張子</td>
797
- <td><tt>.asciidoc</tt>, <tt>.adoc</tt> and <tt>.ad</tt></td>
798
- </tr>
799
- <tr>
800
- <td>例</td>
801
- <td><tt>asciidoc :README, :layout_engine => :erb</tt></td>
802
- </tr>
803
- </table>
804
-
805
- AsciiDocテンプレートからRubyのメソッドを直接呼び出すことができないため、ほぼ全ての場合にlocalsを指定する必要があるでしょう。
806
-
807
- #### Radius テンプレート
808
-
809
- <table>
810
- <tr>
811
- <td>依存</td>
812
- <td><a href="https://github.com/jlong/radius" title="Radius">Radius</a></td>
813
- </tr>
814
- <tr>
815
- <td>ファイル拡張子</td>
816
- <td><tt>.radius</tt></td>
817
- </tr>
818
- <tr>
819
- <td>例</td>
820
- <td><tt>radius :index, :locals => { :key => 'value' }</tt></td>
821
- </tr>
822
- </table>
823
-
824
- RadiusテンプレートからRubyのメソッドを直接呼び出すことができないため、ほぼ全ての場合にlocalsを指定する必要があるでしょう。
825
-
826
- #### Markaby テンプレート
827
-
828
- <table>
829
- <tr>
830
- <td>依存</td>
831
- <td><a href="https://markaby.github.io/" title="Markaby">Markaby</a></td>
832
- </tr>
833
- <tr>
834
- <td>ファイル拡張子</td>
835
- <td><tt>.mab</tt></td>
836
- </tr>
837
- <tr>
838
- <td>例</td>
839
- <td><tt>markaby { h1 "Welcome!" }</tt></td>
840
- </tr>
841
- </table>
842
-
843
- インラインテンプレート用にブロックを取ることもできます(例を参照)。
844
-
845
- #### RABL テンプレート
846
-
847
- <table>
848
- <tr>
849
- <td>依存</td>
850
- <td><a href="https://github.com/nesquena/rabl" title="Rabl">Rabl</a></td>
851
- </tr>
852
- <tr>
853
- <td>ファイル拡張子</td>
854
- <td><tt>.rabl</tt></td>
855
- </tr>
856
- <tr>
857
- <td>例</td>
858
- <td><tt>rabl :index</tt></td>
859
- </tr>
860
- </table>
861
-
862
- #### Slim テンプレート
863
-
864
- <table>
865
- <tr>
866
- <td>依存</td>
867
- <td><a href="http://slim-lang.com/" title="Slim Lang">Slim Lang</a></td>
868
- </tr>
869
- <tr>
870
- <td>ファイル拡張子</td>
871
- <td><tt>.slim</tt></td>
872
- </tr>
873
- <tr>
874
- <td>例</td>
875
- <td><tt>slim :index</tt></td>
876
- </tr>
877
- </table>
878
-
879
- #### Creole テンプレート
880
-
881
- <table>
882
- <tr>
883
- <td>依存</td>
884
- <td><a href="https://github.com/minad/creole" title="Creole">Creole</a></td>
885
- </tr>
886
- <tr>
887
- <td>ファイル拡張子</td>
888
- <td><tt>.creole</tt></td>
889
- </tr>
890
- <tr>
891
- <td>例</td>
892
- <td><tt>creole :wiki, :layout_engine => :erb</tt></td>
893
- </tr>
894
- </table>
895
-
896
- Creoleからメソッドを呼び出すことも、localsに変数を渡すこともできません。
897
- それゆえ、他のレンダリングエンジンとの組み合わせで使うのが普通です。
898
-
899
- ```ruby
900
- erb :overview, :locals => { :text => creole(:introduction) }
901
- ```
902
-
903
- ノート: 他のテンプレート内で`creole`メソッドを呼び出せます。
904
-
905
- ```ruby
906
- %h1 Hello From Haml!
907
- %p= creole(:greetings)
908
- ```
909
-
910
- CreoleからはRubyを呼ぶことができないので、Creoleで書かれたレイアウトを使うことはできません。しかしながら、`:layout_engine`オプションを渡すことでテンプレートのものとは異なるレンダリングエンジンをレイアウトのために使うことができます。
911
-
912
- #### MediaWiki テンプレート
913
-
914
- <table>
915
- <tr>
916
- <td>依存</td>
917
- <td><a href="https://github.com/nricciar/wikicloth" title="WikiCloth">WikiCloth</a></td>
918
- </tr>
919
- <tr>
920
- <td>ファイル拡張子</td>
921
- <td><tt>.mediawiki</tt> および <tt>.mw</tt></td>
922
- </tr>
923
- <tr>
924
- <td>例</td>
925
- <td><tt>mediawiki :wiki, :layout_engine => :erb</tt></td>
926
- </tr>
927
- </table>
928
-
929
- MediaWikiのテンプレートは直接メソッドから呼び出したり、ローカル変数を通すことはできません。それゆえに、通常は別のレンダリングエンジンと組み合わせて利用します。
930
-
931
- ```ruby
932
- erb :overview, :locals => { :text => mediawiki(:introduction) }
933
- ```
934
-
935
- ノート: 他のテンプレートから部分的に`mediawiki`メソッドを呼び出すことも可能です。
936
-
937
- #### CoffeeScript テンプレート
938
-
939
- <table>
940
- <tr>
941
- <td>依存</td>
942
- <td>
943
- <a href="https://github.com/josh/ruby-coffee-script" title="Ruby CoffeeScript">
944
- CoffeeScript
945
- </a> および
946
- <a href="https://github.com/sstephenson/execjs/blob/master/README.md#readme" title="ExecJS">
947
- JavaScriptの起動方法
948
- </a>
949
- </td>
950
- </tr>
951
- <tr>
952
- <td>ファイル拡張子</td>
953
- <td><tt>.coffee</tt></td>
954
- </tr>
955
- <tr>
956
- <td>例</td>
957
- <td><tt>coffee :index</tt></td>
958
- </tr>
959
- </table>
960
-
961
- #### Stylus テンプレート
962
-
963
- <table>
964
- <tr>
965
- <td>依存</td>
966
- <td>
967
- <a href="https://github.com/forgecrafted/ruby-stylus" title="Ruby Stylus">
968
- Stylus
969
- </a> および
970
- <a href="https://github.com/sstephenson/execjs/blob/master/README.md#readme" title="ExecJS">
971
- JavaScriptの起動方法
972
- </a>
973
- </td>
974
- </tr>
975
- <tr>
976
- <td>ファイル拡張子</td>
977
- <td><tt>.styl</tt></td>
978
- </tr>
979
- <tr>
980
- <td>例</td>
981
- <td><tt>stylus :index</tt></td>
982
- </tr>
983
- </table>
984
-
985
- Stylusテンプレートを使えるようにする前に、まず`stylus`と`stylus/tilt`を読み込む必要があります。
986
-
987
- ```ruby
988
- require 'sinatra'
989
- require 'stylus'
990
- require 'stylus/tilt'
991
-
992
- get '/' do
993
- stylus :example
994
- end
995
- ```
996
-
997
- #### Yajl テンプレート
998
-
999
- <table>
1000
- <tr>
1001
- <td>依存</td>
1002
- <td><a href="https://github.com/brianmario/yajl-ruby" title="yajl-ruby">yajl-ruby</a></td>
1003
- </tr>
1004
- <tr>
1005
- <td>ファイル拡張子</td>
1006
- <td><tt>.yajl</tt></td>
1007
- </tr>
1008
- <tr>
1009
- <td>例</td>
1010
- <td>
1011
- <tt>
1012
- yajl :index,
1013
- :locals => { :key => 'qux' },
1014
- :callback => 'present',
1015
- :variable => 'resource'
1016
- </tt>
1017
- </td>
1018
- </tr>
1019
- </table>
1020
-
1021
- テンプレートのソースはRubyの文字列として評価され、その結果のJSON変数は`#to_json`を使って変換されます。
1022
-
1023
- ```ruby
1024
- json = { :foo => 'bar' }
1025
- json[:baz] = key
1026
- ```
1027
-
1028
- `:callback`および`:variable`オプションは、レンダリングされたオブジェクトを装飾するために使うことができます。
1029
-
1030
- ```ruby
1031
- var resource = {"foo":"bar","baz":"qux"}; present(resource);
1032
- ```
1033
-
1034
- #### WLang テンプレート
1035
-
1036
- <table>
1037
- <tr>
1038
- <td>依存</td>
1039
- <td><a href="https://github.com/blambeau/wlang/" title="wlang">wlang</a></td>
1040
- </tr>
1041
- <tr>
1042
- <td>ファイル拡張子</td>
1043
- <td><tt>.wlang</tt></td>
1044
- </tr>
1045
- <tr>
1046
- <td>例</td>
1047
- <td><tt>wlang :index, :locals => { :key => 'value' }</tt></td>
1048
- </tr>
1049
- </table>
1050
-
1051
- WLang内でのRubyメソッドの呼び出しは一般的ではないので、ほとんどの場合にlocalsを指定する必要があるでしょう。しかしながら、WLangで書かれたレイアウトは`yield`をサポートしています。
1052
-
1053
- ### テンプレート内での変数へのアクセス
1054
-
1055
- テンプレートはルーティングハンドラと同じコンテキストの中で評価されます。ルーティングハンドラでセットされたインスタンス変数はテンプレート内で直接使うことができます。
1056
-
1057
- ```ruby
1058
- get '/:id' do
1059
- @foo = Foo.find(params['id'])
1060
- haml '%h1= @foo.name'
1061
- end
1062
- ```
1063
-
1064
- また、ローカル変数のハッシュで明示的に指定することもできます。
1065
-
1066
- ```ruby
1067
- get '/:id' do
1068
- foo = Foo.find(params['id'])
1069
- haml '%h1= bar.name', :locals => { :bar => foo }
1070
- end
1071
- ```
1072
-
1073
- これは他のテンプレート内で部分テンプレートとして表示する典型的な手法です。
1074
-
1075
- ### `yield`を伴うテンプレートとネストしたレイアウト
1076
-
1077
- レイアウトは通常、`yield`を呼ぶ単なるテンプレートに過ぎません。
1078
- そのようなテンプレートは、既に説明した`:template`オプションを通して使われるか、または次のようなブロックを伴ってレンダリングされます。
1079
-
1080
- ```ruby
1081
- erb :post, :layout => false do
1082
- erb :index
1083
- end
1084
- ```
1085
-
1086
- このコードは、`erb :index, :layout => :post`とほぼ等価です。
1087
-
1088
- レンダリングメソッドにブロックを渡すスタイルは、ネストしたレイアウトを作るために最も役立ちます。
1089
-
1090
- ```ruby
1091
- erb :main_layout, :layout => false do
1092
- erb :admin_layout do
1093
- erb :user
1094
- end
1095
- end
1096
- ```
1097
-
1098
- これはまた次のより短いコードでも達成できます。
1099
-
1100
- ```ruby
1101
- erb :admin_layout, :layout => :main_layout do
1102
- erb :user
1103
- end
1104
- ```
1105
-
1106
- 現在、次のレンダリングメソッドがブロックを取れます: `erb`, `haml`,
1107
- `liquid`, `slim `, `wlang`。
1108
- また汎用の`render`メソッドもブロックを取れます。
1109
-
1110
- ### インラインテンプレート(Inline Templates)
1111
-
1112
- テンプレートはソースファイルの最後で定義することもできます。
1113
-
1114
- ```ruby
1115
- require 'sinatra'
1116
-
1117
- get '/' do
1118
- haml :index
1119
- end
1120
-
1121
- __END__
1122
-
1123
- @@ layout
1124
- %html
1125
- = yield
1126
-
1127
- @@ index
1128
- %div.title Hello world!!!!!
1129
- ```
1130
-
1131
- ノート: Sinatraをrequireするソースファイル内で定義されたインラインテンプレートは自動的に読み込まれます。他のソースファイル内にインラインテンプレートがある場合には`enable :inline_templates`を明示的に呼んでください。
1132
-
1133
- ### 名前付きテンプレート(Named Templates)
1134
-
1135
- テンプレートはトップレベルの`template`メソッドで定義することもできます。
1136
-
1137
- ```ruby
1138
- template :layout do
1139
- "%html\n =yield\n"
1140
- end
1141
-
1142
- template :index do
1143
- '%div.title Hello World!'
1144
- end
1145
-
1146
- get '/' do
1147
- haml :index
1148
- end
1149
- ```
1150
-
1151
- 「layout」という名前のテンプレートが存在する場合は、そのテンプレートファイルは他のテンプレートがレンダリングされる度に使用されます。`:layout => false`で個別に、または`set :haml, :layout => false`でデフォルトとして、レイアウトを無効にすることができます。
1152
-
1153
- ```ruby
1154
- get '/' do
1155
- haml :index, :layout => !request.xhr?
1156
- end
1157
- ```
1158
-
1159
- ### ファイル拡張子の関連付け
1160
-
1161
- 任意のテンプレートエンジンにファイル拡張子を関連付ける場合は、`Tilt.register`を使います。例えば、Textileテンプレートに`tt`というファイル拡張子を使いたい場合は、以下のようにします。
1162
-
1163
- ```ruby
1164
- Tilt.register :tt, Tilt[:textile]
1165
- ```
1166
-
1167
- ### オリジナルテンプレートエンジンの追加
1168
-
1169
- まず、Tiltでそのエンジンを登録し、次にレンダリングメソッドを作ります。
1170
-
1171
- ```ruby
1172
- Tilt.register :myat, MyAwesomeTemplateEngine
1173
-
1174
- helpers do
1175
- def myat(*args) render(:myat, *args) end
1176
- end
1177
-
1178
- get '/' do
1179
- myat :index
1180
- end
1181
- ```
1182
-
1183
- これは、`./views/index.myat`をレンダリングします。Tiltについての詳細は、https://github.com/rtomayko/tilt を参照してください。
1184
-
1185
- ### カスタムロジックを使用したテンプレートの探索
1186
-
1187
- オリジナルテンプレートの検索メカニズムを実装するためには、`#find_template`メソッドを実装します。
1188
-
1189
- ```ruby
1190
- configure do
1191
- set :views [ './views/a', './views/b' ]
1192
- end
1193
-
1194
- def find_template(views, name, engine, &block)
1195
- Array(views).each do |v|
1196
- super(v, name, engine, &block)
1197
- end
1198
- end
1199
- ```
1200
-
1201
- ## フィルタ(Filters)
1202
-
1203
- beforeフィルタは、リクエストのルーティングと同じコンテキストで各リクエストの前に評価され、それによってリクエストとレスポンスを変更可能にします。フィルタ内でセットされたインスタンス変数はルーティングとテンプレートからアクセスすることができます。
1204
-
1205
- ```ruby
1206
- before do
1207
- @note = 'Hi!'
1208
- request.path_info = '/foo/bar/baz'
1209
- end
1210
-
1211
- get '/foo/*' do
1212
- @note #=> 'Hi!'
1213
- params['splat'] #=> 'bar/baz'
1214
- end
1215
- ```
1216
-
1217
- afterフィルタは、リクエストのルーティングと同じコンテキストで各リクエストの後に評価され、それによってこれもリクエストとレスポンスを変更可能にします。beforeフィルタとルーティング内でセットされたインスタンス変数はafterフィルタからアクセスすることができます。
1218
-
1219
- ```ruby
1220
- after do
1221
- puts response.status
1222
- end
1223
- ```
1224
-
1225
- ノート: `body`メソッドを使わずにルーティングから文字列を返すだけの場合、その内容はafterフィルタでまだ利用できず、その後に生成されることになります。
1226
-
1227
- フィルタにはオプションとしてパターンを渡すことができ、この場合はリクエストのパスがパターンにマッチした場合にのみフィルタが評価されるようになります。
1228
-
1229
- ```ruby
1230
- before '/protected/*' do
1231
- authenticate!
1232
- end
1233
-
1234
- after '/create/:slug' do |slug|
1235
- session[:last_slug] = slug
1236
- end
1237
- ```
1238
-
1239
- ルーティング同様、フィルタもまた条件を取ることができます。
1240
-
1241
- ```ruby
1242
- before :agent => /Songbird/ do
1243
- # ...
1244
- end
1245
-
1246
- after '/blog/*', :host_name => 'example.com' do
1247
- # ...
1248
- end
1249
- ```
1250
-
1251
- ## ヘルパー(Helpers)
1252
-
1253
- トップレベルの`helpers`メソッドを使用してルーティングハンドラやテンプレートで使うヘルパーメソッドを定義できます。
1254
-
1255
- ```ruby
1256
- helpers do
1257
- def bar(name)
1258
- "#{name}bar"
1259
- end
1260
- end
1261
-
1262
- get '/:name' do
1263
- bar(params['name'])
1264
- end
1265
- ```
1266
-
1267
- あるいは、ヘルパーメソッドをモジュール内で個別に定義することもできます。
1268
-
1269
- ```ruby
1270
- module FooUtils
1271
- def foo(name) "#{name}foo" end
1272
- end
1273
-
1274
- module BarUtils
1275
- def bar(name) "#{name}bar" end
1276
- end
1277
-
1278
- helpers FooUtils, BarUtils
1279
- ```
1280
-
1281
- その効果は、アプリケーションクラスにモジュールをインクルードするのと同じです。
1282
-
1283
- ### セッションの使用
1284
-
1285
- セッションはリクエスト間での状態維持のために使用されます。セッションを有効化すると、ユーザセッションごとに一つのセッションハッシュが与えられます。
1286
-
1287
- ```ruby
1288
- enable :sessions
1289
-
1290
- get '/' do
1291
- "value = " << session[:value].inspect
1292
- end
1293
-
1294
- get '/:value' do
1295
- session[:value] = params['value']
1296
- end
1297
- ```
1298
-
1299
- ノート: `enable :sessions`は実際にはすべてのデータをクッキーに保持します。これは必ずしも期待通りのものにならないかもしれません(例えば、大量のデータを保持することでトラフィックが増大するなど)。Rackセッションミドルウェアの利用が可能であり、その場合は`enable :sessions`を呼ばずに、選択したミドルウェアを他のミドルウェアのときと同じようにして取り込んでください。
1300
-
1301
- ```ruby
1302
- use Rack::Session::Pool, :expire_after => 2592000
1303
-
1304
- get '/' do
1305
- "value = " << session[:value].inspect
1306
- end
1307
-
1308
- get '/:value' do
1309
- session[:value] = params['value']
1310
- end
1311
- ```
1312
-
1313
- セキュリティ向上のため、クッキー内のセッションデータはセッション秘密鍵(session secret)で署名されます。Sinatraによりランダムな秘密鍵が個別に生成されます。しかし、この秘密鍵はアプリケーションの立ち上げごとに変わってしまうので、すべてのアプリケーションのインスタンスで共有できる秘密鍵をセットしたくなるかもしれません。
1314
-
1315
- ```ruby
1316
- set :session_secret, 'super secret'
1317
- ```
1318
-
1319
- 更に、設定変更をしたい場合は、`sessions`の設定においてオプションハッシュを保持することもできます。
1320
-
1321
- ```ruby
1322
- set :sessions, :domain => 'foo.com'
1323
- ```
1324
-
1325
- foo.comのサブドメイン上のアプリ間でセッションを共有化したいときは、代わりにドメインの前に *.* を付けます。
1326
-
1327
- ```ruby
1328
- set :sessions, :domain => '.foo.com'
1329
- ```
1330
-
1331
- #### セッションミドルウェアの選択
1332
-
1333
- `enable :sessions`とすることで、クッキー内の全てのデータを実際に保存してしまうことに注意してください。
1334
- これは、あなたが望む挙動ではない(例えば、大量のデータを保存することでトラフィックが増大してしまう)かもしれません。
1335
- あなたは、次のいずれかの方法によって、任意のRackセッションミドルウェアを使用することができます。
1336
-
1337
- ```ruby
1338
- enable :sessions
1339
- set :session_store, Rack::Session::Pool
1340
- ```
1341
-
1342
- オプションのハッシュを設定するためには、次のようにします。
1343
-
1344
- ```ruby
1345
- set :sessions, :expire_after => 2592000
1346
- set :session_store, Rack::Session::Pool
1347
- ```
1348
-
1349
- 他の方法は`enable :sessions`を**しない**で、他のミドルウェアの選択と同様にあなた自身でミドルウェアを選択することです。
1350
-
1351
- この方法を選択する場合は、セッションベースの保護は**デフォルトで有効にならない**ということに注意することが重要です。
1352
-
1353
- これを満たすためのRackミドルウェアを追加することが必要になります。
1354
-
1355
- ```ruby
1356
- use Rack::Session::Pool, :expire_after => 2592000
1357
- use Rack::Protection::RemoteToken
1358
- use Rack::Protection::SessionHijacking
1359
- ```
1360
-
1361
- より詳しい情報は、「攻撃防御に対する設定」の項を参照してください。
1362
-
1363
- ### 停止(Halting)
1364
-
1365
- フィルタまたはルーティング内で直ちにリクエストを止める場合
1366
-
1367
- ```ruby
1368
- halt
1369
- ```
1370
-
1371
- この際、ステータスを指定することもできます。
1372
-
1373
- ```ruby
1374
- halt 410
1375
- ```
1376
-
1377
- body部を指定することも、
1378
-
1379
- ```ruby
1380
- halt 'ここにbodyを書く'
1381
- ```
1382
-
1383
- ステータスとbody部を指定することも、
1384
-
1385
- ```ruby
1386
- halt 401, '立ち去れ!'
1387
- ```
1388
-
1389
- ヘッダを付けることもできます。
1390
-
1391
- ```ruby
1392
- halt 402, {'Content-Type' => 'text/plain'}, 'リベンジ'
1393
- ```
1394
-
1395
- もちろん、テンプレートを`halt`に結びつけることも可能です。
1396
-
1397
- ```ruby
1398
- halt erb(:error)
1399
- ```
1400
-
1401
- ### パッシング(Passing)
1402
-
1403
- ルーティングは`pass`を使って次のルーティングに飛ばすことができます。
1404
-
1405
- ```ruby
1406
- get '/guess/:who' do
1407
- pass unless params['who'] == 'Frank'
1408
- "見つかっちゃった!"
1409
- end
1410
-
1411
- get '/guess/*' do
1412
- "はずれです!"
1413
- end
1414
- ```
1415
-
1416
- ルーティングブロックからすぐに抜け出し、次にマッチするルーティングを実行します。マッチするルーティングが見当たらない場合は404が返されます。
1417
-
1418
- ### 別ルーティングの誘発
1419
-
1420
- `pass`を使ってルーティングを飛ばすのではなく、他のルーティングを呼んだ結果を得たいという場合があります。
1421
- これは`call`を使用することで実現できます。
1422
-
1423
- ```ruby
1424
- get '/foo' do
1425
- status, headers, body = call env.merge("PATH_INFO" => '/bar')
1426
- [status, headers, body.map(&:upcase)]
1427
- end
1428
-
1429
- get '/bar' do
1430
- "bar"
1431
- end
1432
- ```
1433
-
1434
- ノート: 先の例において、テストを楽にしパフォーマンスを改善するには、`"bar"`を単にヘルパーに移し、`/foo`および`/bar`から使えるようにしたほうが良いです。
1435
-
1436
- リクエストが、その複製物でない同じアプリケーションのインスタンスに送られるようにしたいときは、`call`に代えて`call!`を使ってください。
1437
-
1438
- `call`についての詳細はRackの仕様を参照してください。
1439
-
1440
- ### ボディ、ステータスコードおよびヘッダの設定
1441
-
1442
- ステータスコードおよびレスポンスボディを、ルーティングブロックの戻り値にセットすることが可能であり、これは推奨されています。しかし、あるケースでは実行フローの任意のタイミングでボディをセットしたくなるかもしれません。`body`ヘルパーメソッドを使えばそれができます。そうすると、それ以降、ボディにアクセスするためにそのメソッドを使うことができるようになります。
1443
-
1444
- ```ruby
1445
- get '/foo' do
1446
- body "bar"
1447
- end
1448
-
1449
- after do
1450
- puts body
1451
- end
1452
- ```
1453
-
1454
- また、`body`にはブロックを渡すことができ、これはRackハンドラにより実行されることになります(これはストリーミングを実装するのに使われます。"戻り値"の項を参照してください。)
1455
-
1456
- ボディと同様に、ステータスコードおよびヘッダもセットできます。
1457
-
1458
- ```ruby
1459
- get '/foo' do
1460
- status 418
1461
- headers \
1462
- "Allow" => "BREW, POST, GET, PROPFIND, WHEN",
1463
- "Refresh" => "Refresh: 20; https://www.ietf.org/rfc/rfc2324.txt"
1464
- body "I'm a tea pot!"
1465
- end
1466
- ```
1467
-
1468
- 引数を伴わない`body`、`headers`、`status`などは、それらの現在の値にアクセスするために使えます。
1469
-
1470
- ### ストリーミングレスポンス(Streaming Responses)
1471
-
1472
- レスポンスボディの部分を未だ生成している段階で、データを送り出したいということがあります。極端な例では、クライアントがコネクションを閉じるまでデータを送り続けたいことがあります。`stream`ヘルパーを使えば、独自ラッパーを作る必要はありません。
1473
-
1474
- ```ruby
1475
- get '/' do
1476
- stream do |out|
1477
- out << "それは伝 -\n"
1478
- sleep 0.5
1479
- out << " (少し待つ) \n"
1480
- sleep 1
1481
- out << "- 説になる!\n"
1482
- end
1483
- end
1484
- ```
1485
-
1486
- これはストリーミングAPI、[Server Sent Events](https://w3c.github.io/eventsource/)の実装を可能にし、[WebSockets](https://en.wikipedia.org/wiki/WebSocket)の土台に使うことができます。また、一部のコンテンツが遅いリソースに依存しているときに、スループットを上げるために使うこともできます。
1487
-
1488
- ノート: ストリーミングの挙動、特に並行リクエスト(concurrent requests)の数は、アプリケーションを提供するのに使われるWebサーバに強く依存します。いくつかのサーバは、ストリーミングを全くサポートしません。サーバがストリーミングをサポートしない場合、ボディは`stream`に渡されたブロックの実行が終了した後、一度に全部送られることになります。ストリーミングは、Shotgunを使った場合は全く動作しません。
1489
-
1490
- オプション引数が`keep_open`にセットされている場合、ストリームオブジェクト上で`close`は呼ばれず、実行フローの任意の遅れたタイミングでユーザがこれを閉じることを可能にします。これはRainbowsのようなイベント型サーバ上でしか機能しません。他のサーバでは依然ストリームは閉じられます。
1491
-
1492
- ```ruby
1493
- # config.ru
1494
- require 'sinatra/base'
1495
-
1496
- class App < Sinatra::Base
1497
- connections = []
1498
-
1499
- get '/subscribe' do
1500
- # register a client's interest in server events
1501
- # サーバイベントにおけるクライアントの関心を登録
1502
- stream(:keep_open) do |out|
1503
- connections << out
1504
- # 死んでいるコネクションを排除
1505
- connections.reject!(&:closed?)
1506
- end
1507
- end
1508
-
1509
- post '/:message' do
1510
- connections.each do |out|
1511
- # クライアントへ新規メッセージ到着の通知
1512
- out << params['message'] << "\n"
1513
-
1514
- # クライアントへの再接続の指示
1515
- out.close
1516
- end
1517
-
1518
- # 肯定応答
1519
- "message received"
1520
- end
1521
- end
1522
-
1523
- run App
1524
- ```
1525
-
1526
- ```ruby
1527
- # rainbows.conf
1528
- Rainbows! do
1529
- use :EventMachine
1530
- end
1531
- ````
1532
-
1533
- 次のように起動します。
1534
-
1535
- ```shell
1536
- rainbows -c rainbows.conf
1537
- ```
1538
-
1539
- クライアントはソケットに書き込もうとしている接続を閉じることも可能です。そのため、記述しようとする前に`out.closed?`をチェックすることを勧めます。
1540
-
1541
- ### ロギング(Logging)
1542
-
1543
- リクエストスコープにおいて、`logger`ヘルパーは`Logger`インスタンスを作り出します。
1544
-
1545
- ```ruby
1546
- get '/' do
1547
- logger.info "loading data"
1548
- # ...
1549
- end
1550
- ```
1551
-
1552
- このロガーは、自動でRackハンドラのロギング設定を参照します。ロギングが無効(disabled)にされている場合、このメソッドはダミーオブジェクトを返すので、ルーティングやフィルタにおいて特に心配することはありません。
1553
-
1554
- ノート: ロギングは、`Sinatra::Application`に対してのみデフォルトで有効にされているので、`Sinatra::Base`を継承している場合は、ユーザがこれを有効化する必要があります。
1555
-
1556
- ```ruby
1557
- class MyApp < Sinatra::Base
1558
- configure :production, :development do
1559
- enable :logging
1560
- end
1561
- end
1562
- ```
1563
-
1564
- ロギングミドルウェアが設定されてしまうのを避けるには、`logging`設定を`nil`にセットします。しかしこの場合、`logger`が`nil`を返すことを忘れないように。よくあるユースケースは、オリジナルのロガーをセットしたいときです。Sinatraは、とにかく`env['rack.logger']`で見つかるものを使います。
1565
-
1566
- ### MIMEタイプ(Mime Types)
1567
-
1568
- `send_file`か静的ファイルを使う時、SinatraがMIMEタイプを理解できない場合があります。その時は `mime_type` を使ってファイル拡張子毎に登録してください。
1569
-
1570
- ```ruby
1571
- configure do
1572
- mime_type :foo, 'text/foo'
1573
- end
1574
- ```
1575
-
1576
- これは`content_type`ヘルパーで利用することができます:
1577
-
1578
- ```ruby
1579
- get '/' do
1580
- content_type :foo
1581
- "foo foo foo"
1582
- end
1583
- ```
1584
-
1585
- ### URLの生成
1586
-
1587
- URLを生成するためには`url`ヘルパーメソッドが使えます。Hamlではこのようにします。
1588
-
1589
- ```ruby
1590
- %a{:href => url('/foo')} foo
1591
- ```
1592
-
1593
- これはリバースプロキシおよびRackルーティングを、それらがあれば考慮に入れます。
1594
-
1595
- このメソッドには`to`というエイリアスがあります(以下の例を参照)。
1596
-
1597
- ### ブラウザリダイレクト(Browser Redirect)
1598
-
1599
- `redirect` ヘルパーメソッドを使うことで、ブラウザをリダイレクトさせることができます。
1600
-
1601
- ```ruby
1602
- get '/foo' do
1603
- redirect to('/bar')
1604
- end
1605
- ```
1606
-
1607
- 他に追加されるパラメータは、`halt`に渡される引数と同様に取り扱われます。
1608
-
1609
- ```ruby
1610
- redirect to('/bar'), 303
1611
- redirect 'https://www.google.com/', 'wrong place, buddy'
1612
- ```
1613
-
1614
- また、`redirect back`を使えば、簡単にユーザが来たページへ戻るリダイレクトを作れます。
1615
-
1616
- ```ruby
1617
- get '/foo' do
1618
- "<a href='/bar'>do something</a>"
1619
- end
1620
-
1621
- get '/bar' do
1622
- do_something
1623
- redirect back
1624
- end
1625
- ```
1626
-
1627
- redirectに引数を渡すには、それをクエリーに追加するか、
1628
-
1629
- ```ruby
1630
- redirect to('/bar?sum=42')
1631
- ```
1632
-
1633
- または、セッションを使います。
1634
-
1635
- ```ruby
1636
- enable :sessions
1637
-
1638
- get '/foo' do
1639
- session[:secret] = 'foo'
1640
- redirect to('/bar')
1641
- end
1642
-
1643
- get '/bar' do
1644
- session[:secret]
1645
- end
1646
- ```
1647
-
1648
- ### キャッシュ制御(Cache Control)
1649
-
1650
- ヘッダを正しく設定することが、適切なHTTPキャッシングのための基礎となります。
1651
-
1652
- キャッシュ制御ヘッダ(Cache-Control header)は、次のように簡単に設定できます。
1653
-
1654
- ```ruby
1655
- get '/' do
1656
- cache_control :public
1657
- "キャッシュしました!"
1658
- end
1659
- ```
1660
-
1661
- ヒント: キャッシングをbeforeフィルタ内で設定します。
1662
-
1663
- ```ruby
1664
- before do
1665
- cache_control :public, :must_revalidate, :max_age => 60
1666
- end
1667
- ```
1668
-
1669
- `expires`ヘルパーを対応するヘッダに使っている場合は、キャッシュ制御は自動で設定されます。
1670
-
1671
- ```ruby
1672
- before do
1673
- expires 500, :public, :must_revalidate
1674
- end
1675
- ```
1676
-
1677
- キャッシュを適切に使うために、`etag`または`last_modified`を使うことを検討してください。これらのヘルパーを、重い仕事をさせる *前* に呼ぶことを推奨します。そうすれば、クライアントが既にキャッシュに最新版を持っている場合はレスポンスを直ちに破棄するようになります。
1678
-
1679
- ```ruby
1680
- get '/article/:id' do
1681
- @article = Article.find params['id']
1682
- last_modified @article.updated_at
1683
- etag @article.sha1
1684
- erb :article
1685
- end
1686
- ```
1687
-
1688
- また、[weak ETag](https://ja.wikipedia.org/wiki/HTTP_ETag#Strong_and_weak_validation)を使うこともできます。
1689
-
1690
- ```ruby
1691
- etag @article.sha1, :weak
1692
- ```
1693
-
1694
- これらのヘルパーは、キャッシングをしてくれませんが、必要な情報をキャッシュに与えてくれます。もし手早いリバースプロキシキャッシングの解決策をお探しなら、 [rack-cache](https://github.com/rtomayko/rack-cache)を試してください。
1695
-
1696
- ```ruby
1697
- require "rack/cache"
1698
- require "sinatra"
1699
-
1700
- use Rack::Cache
1701
-
1702
- get '/' do
1703
- cache_control :public, :max_age => 36000
1704
- sleep 5
1705
- "hello"
1706
- end
1707
- ```
1708
-
1709
- `:static_cache_control`設定(以下を参照)を、キャッシュ制御ヘッダ情報を静的ファイルに追加するために使ってください。
1710
-
1711
- RFC 2616によれば、アプリケーションは、If-MatchまたはIf-None-Matchヘッダが`*`に設定されている場合には、要求されたリソースが既に存在するか否かに応じて、異なる振る舞いをすべきとなっています。Sinatraは、getのような安全なリクエストおよびputのような冪等なリクエストは既に存在しているものとして仮定し、一方で、他のリソース(例えば、postリクエスト)は新たなリソースとして取り扱われるよう仮定します。この振る舞いは、`:new_resource`オプションを渡すことで変更できます。
1712
-
1713
- ```ruby
1714
- get '/create' do
1715
- etag '', :new_resource => true
1716
- Article.create
1717
- erb :new_article
1718
- end
1719
- ```
1720
-
1721
- ここでもWeak ETagを使いたい場合は、`:kind`オプションを渡してください。
1722
-
1723
- ```ruby
1724
- etag '', :new_resource => true, :kind => :weak
1725
- ```
1726
-
1727
- ### ファイルの送信
1728
-
1729
- ファイルを送信するには、`send_file`ヘルパーメソッドを使います。
1730
-
1731
- ```ruby
1732
- get '/' do
1733
- send_file 'foo.png'
1734
- end
1735
- ```
1736
-
1737
- これはオプションを取ることもできます。
1738
-
1739
- ```ruby
1740
- send_file 'foo.png', :type => :jpg
1741
- ```
1742
-
1743
- オプション一覧
1744
-
1745
- <dl>
1746
- <dt>filename</dt>
1747
- <dd>ファイル名。デフォルトは実際のファイル名。</dd>
1748
-
1749
- <dt>last_modified</dt>
1750
- <dd>Last-Modifiedヘッダの値。デフォルトはファイルのmtime。</dd>
1751
-
1752
- <dt>type</dt>
1753
- <dd>コンテンツの種類。設定がない場合、ファイル拡張子から類推される。</dd>
1754
-
1755
- <dt>disposition</dt>
1756
- <dd>
1757
- Content-Dispositionに使われる。許容値: <tt>nil</tt> (デフォルト)、
1758
- <tt>:attachment</tt> および <tt>:inline</tt>
1759
- </dd>
1760
-
1761
- <dt>length</dt>
1762
- <dd>Content-Lengthヘッダ。デフォルトはファイルサイズ。</dd>
1763
-
1764
- <dt>status</dt>
1765
- <dd>
1766
- 送られるステータスコード。静的ファイルをエラーページとして送るときに便利。
1767
-
1768
- Rackハンドラでサポートされている場合は、Rubyプロセスからのストリーミング以外の手段が使われる。このヘルパーメソッドを使うと、Sinatraは自動で範囲リクエスト(range requests)を扱う。
1769
- </dd>
1770
- </dl>
1771
-
1772
- ### リクエストオブジェクトへのアクセス
1773
-
1774
- 受信するリクエストオブジェクトは、`request`メソッドを通じてリクエストレベル(フィルタ、ルーティング、エラーハンドラ)からアクセスすることができます。
1775
-
1776
- ```ruby
1777
- # アプリケーションが http://example.com/example で動作している場合
1778
- get '/foo' do
1779
- t = %w[text/css text/html application/javascript]
1780
- request.accept # ['text/html', '*/*']
1781
- request.accept? 'text/xml' # true
1782
- request.preferred_type(t) # 'text/html'
1783
- request.body # クライアントによって送信されたリクエストボディ(下記参照)
1784
- request.scheme # "http"
1785
- request.script_name # "/example"
1786
- request.path_info # "/foo"
1787
- request.port # 80
1788
- request.request_method # "GET"
1789
- request.query_string # ""
1790
- request.content_length # request.bodyの長さ
1791
- request.media_type # request.bodyのメディアタイプ
1792
- request.host # "example.com"
1793
- request.get? # true (他の動詞にも同種メソッドあり)
1794
- request.form_data? # false
1795
- request["some_param"] # some_param変数の値。[]はパラメータハッシュのショートカット
1796
- request.referrer # クライアントのリファラまたは'/'
1797
- request.user_agent # ユーザエージェント (:agent 条件によって使用される)
1798
- request.cookies # ブラウザクッキーのハッシュ
1799
- request.xhr? # Ajaxリクエストかどうか
1800
- request.url # "http://example.com/example/foo"
1801
- request.path # "/example/foo"
1802
- request.ip # クライアントのIPアドレス
1803
- request.secure? # false (sslではtrueになる)
1804
- request.forwarded? # true (リバースプロキシの裏で動いている場合)
1805
- request.env # Rackによって渡された生のenvハッシュ
1806
- end
1807
- ```
1808
-
1809
- `script_name`や`path_info`などのオプションは次のように利用することもできます。
1810
-
1811
- ```ruby
1812
- before { request.path_info = "/" }
1813
-
1814
- get "/" do
1815
- "全てのリクエストはここに来る"
1816
- end
1817
- ```
1818
-
1819
- `request.body`はIOまたはStringIOのオブジェクトです。
1820
-
1821
- ```ruby
1822
- post "/api" do
1823
- request.body.rewind # 既に読まれているときのため
1824
- data = JSON.parse request.body.read
1825
- "Hello #{data['name']}!"
1826
- end
1827
- ```
1828
-
1829
- ### アタッチメント(Attachments)
1830
-
1831
- `attachment`ヘルパーを使って、レスポンスがブラウザに表示されるのではなく、ディスクに保存されることをブラウザに対し通知することができます。
1832
-
1833
- ```ruby
1834
- get '/' do
1835
- attachment
1836
- "保存しました!"
1837
- end
1838
- ```
1839
-
1840
- ファイル名を渡すこともできます。
1841
-
1842
- ```ruby
1843
- get '/' do
1844
- attachment "info.txt"
1845
- "保存しました!"
1846
- end
1847
- ```
1848
-
1849
- ### 日付と時刻の取り扱い
1850
-
1851
- Sinatraは`time_for`ヘルパーメソッドを提供しており、それは与えられた値からTimeオブジェクトを生成します。これはまた`DateTime`、`Date`および類似のクラスを変換できます。
1852
-
1853
- ```ruby
1854
- get '/' do
1855
- pass if Time.now > time_for('Dec 23, 2012')
1856
- "まだ時間がある"
1857
- end
1858
- ```
1859
-
1860
- このメソッドは、`expires`、`last_modified`といった種類のものの内部で使われています。そのため、アプリケーションにおいて、`time_for`をオーバーライドすることでそれらのメソッドの挙動を簡単に拡張できます。
1861
-
1862
- ```ruby
1863
- helpers do
1864
- def time_for(value)
1865
- case value
1866
- when :yesterday then Time.now - 24*60*60
1867
- when :tomorrow then Time.now + 24*60*60
1868
- else super
1869
- end
1870
- end
1871
- end
1872
-
1873
- get '/' do
1874
- last_modified :yesterday
1875
- expires :tomorrow
1876
- "hello"
1877
- end
1878
- ```
1879
-
1880
- ### テンプレートファイルの探索
1881
-
1882
- `find_template`ヘルパーは、レンダリングのためのテンプレートファイルを見つけるために使われます。
1883
-
1884
- ```ruby
1885
- find_template settings.views, 'foo', Tilt[:haml] do |file|
1886
- puts "could be #{file}"
1887
- end
1888
- ```
1889
-
1890
- この例はあまり有益ではありません。しかし、このメソッドを、独自の探索機構で働くようオーバーライドするなら有益になります。例えば、複数のビューディレクトリを使えるようにしたいときがあります。
1891
-
1892
-
1893
- ```ruby
1894
- set :views, ['views', 'templates']
1895
-
1896
- helpers do
1897
- def find_template(views, name, engine, &block)
1898
- Array(views).each { |v| super(v, name, engine, &block) }
1899
- end
1900
- end
1901
- ```
1902
-
1903
- 他の例としては、異なるエンジン用の異なるディレクトリを使う場合です。
1904
-
1905
- ```ruby
1906
- set :views, :sass => 'views/sass', :haml => 'templates', :default => 'views'
1907
-
1908
- helpers do
1909
- def find_template(views, name, engine, &block)
1910
- _, folder = views.detect { |k,v| engine == Tilt[k] }
1911
- folder ||= views[:default]
1912
- super(folder, name, engine, &block)
1913
- end
1914
- end
1915
- ```
1916
-
1917
- これをエクステンションとして書いて、他の人と簡単に共有することもできます!
1918
-
1919
- ノート: `find_template`はファイルが実際に存在するかのチェックをしませんが、与えられたブロックをすべての可能なパスに対し呼び出します。これがパフォーマンス上の問題にはならないのは、`render`はファイルを見つけると直ちに`break`を使うからです。また、テンプレートの場所(および内容)は、developmentモードでの起動でない限りはキャッシュされます。このことは、複雑なメソッド(a really crazy method)を書いた場合は記憶しておく必要があります。
1920
-
1921
- ## コンフィギュレーション(Configuration)
1922
-
1923
- どの環境でも起動時に1回だけ実行されます。
1924
-
1925
- ```ruby
1926
- configure do
1927
- # 1つのオプションをセット
1928
- set :option, 'value'
1929
-
1930
- # 複数のオプションをセット
1931
- set :a => 1, :b => 2
1932
-
1933
- # `set :option, true`と同じ
1934
- enable :option
1935
-
1936
- # `set :option, false`と同じ
1937
- disable :option
1938
-
1939
- # ブロックを使って動的な設定をすることもできます。
1940
- set(:css_dir) { File.join(views, 'css') }
1941
- end
1942
- ```
1943
-
1944
- 環境設定(`APP_ENV`環境変数)が`:production`に設定されている時だけ実行する方法:
1945
-
1946
- ```ruby
1947
- configure :production do
1948
- ...
1949
- end
1950
- ```
1951
-
1952
- 環境設定が`:production`か`:test`に設定されている時だけ実行する方法:
1953
-
1954
- ```ruby
1955
- configure :production, :test do
1956
- ...
1957
- end
1958
- ```
1959
-
1960
- 設定したオプションには`settings`からアクセスできます:
1961
-
1962
- ```ruby
1963
- configure do
1964
- set :foo, 'bar'
1965
- end
1966
-
1967
- get '/' do
1968
- settings.foo? # => true
1969
- settings.foo # => 'bar'
1970
- ...
1971
- end
1972
- ```
1973
-
1974
- ### 攻撃防御に対する設定
1975
-
1976
- Sinatraは[Rack::Protection](https://github.com/sinatra/sinatra/tree/master/rack-protection#readme)を使用することで、アプリケーションを一般的な日和見的攻撃から守っています。これは簡単に無効化できます(が、アプリケーションに大量の一般的な脆弱性を埋め込むことになってしまいます)。
1977
-
1978
- ```ruby
1979
- disable :protection
1980
- ```
1981
-
1982
- ある1つの防御を無効にするには、`protection`にハッシュでオプションを指定します。
1983
-
1984
- ```ruby
1985
- set :protection, :except => :path_traversal
1986
- ```
1987
-
1988
- 配列を渡すことで、複数の防御を無効にすることもできます。
1989
-
1990
- ```ruby
1991
- set :protection, :except => [:path_traversal, :session_hijacking]
1992
- ```
1993
-
1994
- デフォルトでSinatraは、`:sessions`が有効になっている場合、セッションベースの防御だけを設定します。しかし、自身でセッションを設定したい場合があります。その場合は、`:session`オプションを渡すことにより、セッションベースの防御を設定することができます。
1995
-
1996
- ```ruby
1997
- use Rack::Session::Pool
1998
- set :protection, :session => true
1999
- ```
2000
-
2001
- ### 利用可能な設定
2002
-
2003
- <dl>
2004
- <dt>absolute_redirects</dt>
2005
- <dd>
2006
- 無効のとき、Sinatraは相対リダイレクトを許容するが、RFC 2616 (HTTP 1.1)は絶対リダイレクトのみを許容するので、これには準拠しなくなる。
2007
- </dd>
2008
- <dd>
2009
- アプリケーションが、適切に設定されていないリバースプロキシの裏で走っている場合は有効。ノート: <tt>url</tt>ヘルパーは、第2引数に<tt>false</tt>を渡さない限り、依然として絶対URLを生成する。
2010
- </dd>
2011
- <dd>デフォルトは無効。</dd>
2012
-
2013
- <dt>add_charset</dt>
2014
- <dd>
2015
- Mimeタイプ <tt>content_type</tt>ヘルパーが自動的にキャラクタセット情報をここに追加する。このオプションは書き換えるのではなく、値を追加するようにすること。
2016
- <tt>settings.add_charset << "application/foobar"</tt>
2017
- </dd>
2018
-
2019
- <dt>app_file</dt>
2020
- <dd>
2021
- メインのアプリケーションファイルのパスであり、プロジェクトのルート、viewsおよびpublicフォルダを見つけるために使われる。
2022
- </dd>
2023
-
2024
- <dt>bind</dt>
2025
- <dd>バインドするIPアドレス(デフォルト: `environment`がdevelopmentにセットされているときは、<tt>0.0.0.0</tt> <em>または</em> <tt>localhost</tt>)。ビルトインサーバでのみ使われる。</dd>
2026
-
2027
- <dt>default_encoding</dt>
2028
- <dd>不明なときに仮定されるエンコーディング(デフォルトは<tt>"utf-8"</tt>)。</dd>
2029
-
2030
- <dt>dump_errors</dt>
2031
- <dd>ログにおけるエラーの表示。</dd>
2032
-
2033
- <dt>environment</dt>
2034
- <dd>
2035
- 現在の環境。デフォルトは<tt>ENV['APP_ENV']</tt>、それが無い場合は<tt>"development"</tt>。
2036
- </dd>
2037
-
2038
- <dt>logging</dt>
2039
- <dd>ロガーの使用。</dd>
2040
-
2041
- <dt>lock</dt>
2042
- <dd>
2043
- 各リクエスト周りのロックの配置で、Rubyプロセスごとにリクエスト処理を並行して走らせるようにする。
2044
- </dd>
2045
- <dd>アプリケーションがスレッドセーフでなければ有効。デフォルトは無効。</dd>
2046
-
2047
- <dt>method_override</dt>
2048
- <dd>
2049
- put/deleteフォームを、それらをサポートしないブラウザで使えるように<tt>_method</tt>のおまじないを使えるようにする。
2050
- </dd>
2051
-
2052
- <dt>port</dt>
2053
- <dd>待ち受けポート。ビルトインサーバのみで有効。</dd>
2054
-
2055
- <dt>prefixed_redirects</dt>
2056
- <dd>
2057
- 絶対パスが与えられていないときに、リダイレクトに<tt>request.script_name</tt>を挿入するか否かの設定。これにより<tt>redirect '/foo'</tt>は、<tt>redirect to('/foo')</tt>のように振る舞う。デフォルトは無効。
2058
- </dd>
2059
-
2060
- <dt>protection</dt>
2061
- <dd>Web攻撃防御を有効にするか否かの設定。上述の攻撃防御の項を参照。</dd>
2062
-
2063
- <dt>public_dir</dt>
2064
- <dd><tt>public_folder</tt>のエイリアス。以下を参照。</dd>
2065
-
2066
- <dt>public_folder</dt>
2067
- <dd>
2068
- publicファイルが提供されるディレクトリのパス。静的ファイルの提供が有効になっている場合にのみ使われる (以下の<tt>static</tt>設定を参照)。設定されていない場合、<tt>app_file</tt>設定から推定。
2069
- </dd>
2070
-
2071
- <dt>reload_templates</dt>
2072
- <dd>
2073
- リクエスト間でテンプレートを再ロードするか否かの設定。developmentモードでは有効。
2074
- </dd>
2075
-
2076
- <dt>root</dt>
2077
- <dd>
2078
- プロジェクトのルートディレクトリのパス。設定されていない場合、<tt>app_file</tt>設定から推定。
2079
- </dd>
2080
-
2081
- <dt>raise_errors</dt>
2082
- <dd>
2083
- 例外発生の設定(アプリケーションは止まる)。<tt>environment</tt>が<tt>"test"</tt>に設定されているときはデフォルトは有効。それ以外は無効。
2084
- </dd>
2085
-
2086
- <dt>run</dt>
2087
- <dd>
2088
- 有効のとき、SinatraがWebサーバの起動を取り扱う。rackupまたは他の手段を使うときは有効にしないこと。
2089
- </dd>
2090
-
2091
- <dt>running</dt>
2092
- <dd>ビルトインサーバが稼働中か?この設定を変更しないこと!</dd>
2093
-
2094
- <dt>server</dt>
2095
- <dd>
2096
- ビルトインサーバとして使用するサーバまたはサーバ群の指定。指定順位は優先度を表し、デフォルトはRuby実装に依存。
2097
- </dd>
2098
-
2099
- <dt>sessions</dt>
2100
- <dd>
2101
- <tt>Rack::Session::Cookie</tt>を使ったクッキーベースのセッションサポートの有効化。詳しくは、'セッションの使用'の項を参照のこと。
2102
- </dd>
2103
-
2104
- <dt>show_exceptions</dt>
2105
- <dd>
2106
- 例外発生時にブラウザにスタックトレースを表示する。<tt>environment</tt>が<tt>"development"</tt>に設定されているときは、デフォルトで有効。それ以外は無効。
2107
- </dd>
2108
- <dd>
2109
- また、<tt>:after_handler</tt>をセットすることができ、これにより、ブラウザにスタックトレースを表示する前に、アプリケーション固有のエラーハンドリングを起動させられる。
2110
- </dd>
2111
-
2112
- <dt>static</dt>
2113
- <dd>Sinatraが静的ファイルの提供を取り扱うかの設定。</dd>
2114
- <dd>その取り扱いができるサーバを使う場合は無効。</dd>
2115
- <dd>無効化でパフォーマンスは改善する</dd>
2116
- <dd>
2117
- クラッシックスタイルではデフォルトで有効。モジュラースタイルでは無効。
2118
- </dd>
2119
-
2120
- <dt>static_cache_control</dt>
2121
- <dd>
2122
- Sinatraが静的ファイルを提供するときこれをセットして、レスポンスに<tt>Cache-Control</tt>ヘッダを追加するようにする。<tt>cache_control</tt>ヘルパーを使うこと。デフォルトは無効。
2123
- </dd>
2124
- <dd>
2125
- 複数の値をセットするときは明示的に配列を使う:
2126
- <tt>set :static_cache_control, [:public, :max_age => 300]</tt>
2127
- </dd>
2128
-
2129
- <dt>threaded</dt>
2130
- <dd>
2131
- <tt>true</tt>に設定されているときは、サーバにリクエストを処理するために<tt>EventMachine.defer</tt>を使うことを通知する。
2132
- </dd>
2133
-
2134
- <dt>views</dt>
2135
- <dd>
2136
- ビューディレクトリのパス。設定されていない場合、<tt>app_file</tt>設定から推定する。
2137
- </dd>
2138
-
2139
- <dt>x_cascade</dt>
2140
- <dd>
2141
- マッチするルーティングが無い場合に、X-Cascadeヘッダをセットするか否かの設定。デフォルトは<tt>true</tt>。
2142
- </dd>
2143
- </dl>
2144
-
2145
- ## 環境設定(Environments)
2146
-
2147
- 3種類の既定環境、`"development"`、`"production"`および`"test"`があります。環境は、`APP_ENV`環境変数を通して設定できます。デフォルト値は、`"development"`です。`"development"`環境において、すべてのテンプレートは、各リクエスト間で再ロードされ、そして、特別の`not_found`および`error`ハンドラがブラウザにスタックトレースを表示します。`"production"`および`"test"`環境においては、テンプレートはデフォルトでキャッシュされます。
2148
-
2149
- 異なる環境を走らせるには、`APP_ENV`環境変数を設定します。
2150
-
2151
- ```shell
2152
- APP_ENV=production ruby my_app.rb
2153
- ```
2154
-
2155
- 既定メソッド、`development?`、`test?`および`production?`を、現在の環境設定を確認するために使えます。
2156
-
2157
- ```ruby
2158
- get '/' do
2159
- if settings.development?
2160
- "development!"
2161
- else
2162
- "not development!"
2163
- end
2164
- end
2165
- ```
2166
-
2167
- ## エラーハンドリング(Error Handling)
2168
-
2169
- エラーハンドラはルーティングおよびbeforeフィルタと同じコンテキストで実行されます。すなわちこれは、`haml`、`erb`、`halt`といった便利なものが全て使えることを意味します。
2170
-
2171
- ### 未検出(Not Found)
2172
-
2173
- `Sinatra::NotFound`例外が発生したとき、またはレスポンスのステータスコードが404のときに、`not_found`ハンドラが発動します。
2174
-
2175
- ```ruby
2176
- not_found do
2177
- 'ファイルが存在しません'
2178
- end
2179
- ```
2180
-
2181
- ### エラー(Error)
2182
-
2183
- `error`ハンドラはルーティングブロックまたはフィルタ内で例外が発生したときはいつでも発動します。
2184
- しかし、環境設定がdevelopmentの場合は`:after_handler`を設定している場合のみ発動するようになります。
2185
-
2186
- ```ruby
2187
- set :show_exceptions, :after_handler
2188
- ```
2189
-
2190
- 例外オブジェクトはRack変数`sinatra.error`から取得できます。
2191
-
2192
- ```ruby
2193
- error do
2194
- 'エラーが発生しました。 - ' + env['sinatra.error'].message
2195
- end
2196
- ```
2197
-
2198
- エラーをカスタマイズする場合は、
2199
-
2200
- ```ruby
2201
- error MyCustomError do
2202
- 'エラーメッセージ...' + env['sinatra.error'].message
2203
- end
2204
- ```
2205
-
2206
- と書いておいて、下記のように呼び出します。
2207
-
2208
- ```ruby
2209
- get '/' do
2210
- raise MyCustomError, '何かがまずかったようです'
2211
- end
2212
- ```
2213
-
2214
- そうするとこうなります。
2215
-
2216
- ```
2217
- エラーメッセージ... 何かがまずかったようです
2218
- ```
2219
-
2220
- あるいは、ステータスコードに対応するエラーハンドラを設定することもできます。
2221
-
2222
- ```ruby
2223
- error 403 do
2224
- 'Access forbidden'
2225
- end
2226
-
2227
- get '/secret' do
2228
- 403
2229
- end
2230
- ```
2231
-
2232
- 範囲指定もできます。
2233
-
2234
- ```ruby
2235
- error 400..510 do
2236
- 'Boom'
2237
- end
2238
- ```
2239
-
2240
- Sinatraを開発環境の下で実行している場合は、特別な`not_found`および`error`ハンドラが導入され、これは親切なスタックトレースと追加のデバッギング情報をブラウザに表示します。
2241
-
2242
- ## Rackミドルウェア(Rack Middleware)
2243
-
2244
- SinatraはRuby製Webフレームワークのミニマルな標準的インタフェースである[Rack](https://rack.github.io/)上に構築されています。アプリケーションデベロッパーにとってRackにおける最も興味深い機能は、「ミドルウェア(middleware)」をサポートしていることであり、これは、サーバとアプリケーションとの間に置かれ、HTTPリクエスト/レスポンスを監視および/または操作することで、各種の汎用的機能を提供するコンポーネントです。
2245
-
2246
- Sinatraはトップレベルの`use`メソッドを通して、Rackミドルウェアパイプラインの構築を楽にします。
2247
-
2248
- ```ruby
2249
- require 'sinatra'
2250
- require 'my_custom_middleware'
2251
-
2252
- use Rack::Lint
2253
- use MyCustomMiddleware
2254
-
2255
- get '/hello' do
2256
- 'Hello World'
2257
- end
2258
- ```
2259
-
2260
- `use`の文法は、[Rack::Builder](http://www.rubydoc.info/github/rack/rack/master/Rack/Builder)DSLで定義されているそれ(rackupファイルで最もよく使われる)と同じです。例えば `use`メソッドは複数の引数、そしてブロックも取ることができます。
2261
-
2262
- ```ruby
2263
- use Rack::Auth::Basic do |username, password|
2264
- username == 'admin' && password == 'secret'
2265
- end
2266
- ```
2267
-
2268
- Rackは、ロギング、デバッギング、URLルーティング、認証、セッション管理など、多様な標準的ミドルウェアを共に配布されています。Sinatraはその多くのコンポーネントを自動で使うよう基本設定されているため、通常、それらを`use`で明示的に指定する必要はありません。
2269
-
2270
- 便利なミドルウェアを以下で見つけられます。
2271
-
2272
- [rack](https://github.com/rack/rack/tree/master/lib/rack)、
2273
- [rack-contrib](https://github.com/rack/rack-contrib#readm)、
2274
- または[Rack wiki](https://github.com/rack/rack/wiki/List-of-Middleware)。
2275
-
2276
- ## テスト(Testing)
2277
-
2278
- SinatraでのテストはRackベースのテストライブラリまたはフレームワークを使って書くことができます。[Rack::Test](http://www.rubydoc.info/github/brynary/rack-test/master/frames)をお薦めします。
2279
-
2280
- ```ruby
2281
- require 'my_sinatra_app'
2282
- require 'minitest/autorun'
2283
- require 'rack/test'
2284
-
2285
- class MyAppTest < Minitest::Test
2286
- include Rack::Test::Methods
2287
-
2288
- def app
2289
- Sinatra::Application
2290
- end
2291
-
2292
- def test_my_default
2293
- get '/'
2294
- assert_equal 'Hello World!', last_response.body
2295
- end
2296
-
2297
- def test_with_params
2298
- get '/meet', :name => 'Frank'
2299
- assert_equal 'Hello Frank!', last_response.body
2300
- end
2301
-
2302
- def test_with_user_agent
2303
- get '/', {}, 'HTTP_USER_AGENT' => 'Songbird'
2304
- assert_equal "Songbirdを使ってます!", last_response.body
2305
- end
2306
- end
2307
- ```
2308
-
2309
- ノート: モジュラースタイルでSinatraを使う場合は、上記`Sinatra::Application`をアプリケーションのクラス名に置き換えてください。
2310
-
2311
- ## Sinatra::Base - ミドルウェア、ライブラリおよびモジュラーアプリ
2312
-
2313
- 軽量なアプリケーションであれば、トップレベルでアプリケーションを定義していくことはうまくいきますが、再利用性可能なコンポーネント、例えばRackミドルウェア、RailsのMetal、サーバコンポーネントを含むシンプルなライブラリ、あるいはSinatraの拡張プログラムを構築するような場合、これは無視できない欠点を持つものとなります。トップレベルは、軽量なアプリケーションのスタイルにおける設定(例えば、単一のアプリケーションファイル、`./public`および`./views`ディレクトリ、ロギング、例外詳細ページなど)を仮定しています。そこで`Sinatra::Base`の出番です。
2314
-
2315
- ```ruby
2316
- require 'sinatra/base'
2317
-
2318
- class MyApp < Sinatra::Base
2319
- set :sessions, true
2320
- set :foo, 'bar'
2321
-
2322
- get '/' do
2323
- 'Hello world!'
2324
- end
2325
- end
2326
- ```
2327
-
2328
- `Sinatra::Base`のサブクラスで利用できるメソッドは、トップレベルDSLで利用できるものと全く同じです。ほとんどのトップレベルで記述されたアプリは、以下の2点を修正することで`Sinatra::Base`コンポーネントに変えることができます。
2329
-
2330
- * `sinatra`の代わりに`sinatra/base`を読み込む
2331
- (そうしない場合、SinatraのDSLメソッドの全てがmainの名前空間にインポートされます)
2332
- * ルーティング、エラーハンドラ、フィルタ、オプションを`Sinatra::Base`のサブクラスに書く
2333
-
2334
- `Sinatra::Base`はまっさらです。ビルトインサーバを含む、ほとんどのオプションがデフォルトで無効になっています。利用可能なオプションとその挙動の詳細については[Configuring Settings](http://www.sinatrarb.com/configuration.html)(英語)をご覧ください。
2335
-
2336
- もしもクラシックスタイルと同じような挙動のアプリケーションをトップレベルで定義させる必要があれば、`Sinatra::Application`をサブクラス化させてください。
2337
-
2338
- ```ruby
2339
- require "sinatra/base"
2340
-
2341
- class MyApp < Sinatra::Application
2342
- get "/" do
2343
- 'Hello world!'
2344
- end
2345
- end
2346
- ```
2347
-
2348
- ### モジュラースタイル vs クラッシックスタイル
2349
-
2350
- 一般的認識と違って、クラッシックスタイルを使うことに問題はなにもありません。それがそのアプリケーションに合っているのであれば、モジュラーアプリケーションに移行する必要はありません。
2351
-
2352
- モジュラースタイルを使わずにクラッシックスタイルを使った場合の一番の不利な点は、Rubyプロセスごとにただ一つのSinatraアプリケーションしか持てない点です。複数が必要な場合はモジュラースタイルに移行してください。モジュラースタイルとクラッシックスタイルを混合できないということはありません。
2353
-
2354
- 一方のスタイルから他方へ移行する場合、デフォルト設定がわずかに異なる点に注意が必要です。
2355
-
2356
- <table>
2357
- <tr>
2358
- <th>設定</th>
2359
- <th>クラッシック</th>
2360
- <th>モジュラー</th>
2361
- <th>モジュラー</th>
2362
- </tr>
2363
-
2364
- <tr>
2365
- <td>app_file</td>
2366
- <td>sinatraを読み込むファイル</td>
2367
- <td>Sinatra::Baseをサブクラス化したファイル</td>
2368
- <td>Sinatra::Applicationをサブクラス化したファイル</td>
2369
- </tr>
2370
-
2371
- <tr>
2372
- <td>run</td>
2373
- <td>$0 == app_file</td>
2374
- <td>false</td>
2375
- <td>false</td>
2376
- </tr>
2377
-
2378
- <tr>
2379
- <td>logging</td>
2380
- <td>true</td>
2381
- <td>false</td>
2382
- <td>true</td>
2383
- </tr>
2384
-
2385
- <tr>
2386
- <td>method_override</td>
2387
- <td>true</td>
2388
- <td>false</td>
2389
- <td>true</td>
2390
- </tr>
2391
-
2392
- <tr>
2393
- <td>inline_templates</td>
2394
- <td>true</td>
2395
- <td>false</td>
2396
- <td>true</td>
2397
- </tr>
2398
-
2399
- <tr>
2400
- <td>static</td>
2401
- <td>true</td>
2402
- <td>File.exist?(public_folder)</td>
2403
- <td>true</td>
2404
- </tr>
2405
- </table>
2406
-
2407
- ### モジュラーアプリケーションの提供
2408
-
2409
- モジュラーアプリケーションを開始、つまり`run!`を使って開始させる二種類のやり方があります。
2410
-
2411
- ```ruby
2412
- # my_app.rb
2413
- require 'sinatra/base'
2414
-
2415
- class MyApp < Sinatra::Base
2416
- # ... アプリケーションのコードを書く ...
2417
-
2418
- # Rubyファイルが直接実行されたらサーバを立ち上げる
2419
- run! if app_file == $0
2420
- end
2421
- ```
2422
-
2423
- として、次のように起動するか、
2424
-
2425
- ```shell
2426
- ruby my_app.rb
2427
- ```
2428
-
2429
- または、Rackハンドラを使えるようにする`config.ru`ファイルを書いて、
2430
-
2431
- ```ruby
2432
- # config.ru (rackupで起動)
2433
- require './my_app'
2434
- run MyApp
2435
- ```
2436
-
2437
- 起動します。
2438
-
2439
- ```shell
2440
- rackup -p 4567
2441
- ```
2442
-
2443
- ### config.ruを用いたクラッシックスタイルアプリケーションの使用
2444
-
2445
- アプリケーションファイルと、
2446
-
2447
- ```ruby
2448
- # app.rb
2449
- require 'sinatra'
2450
-
2451
- get '/' do
2452
- 'Hello world!'
2453
- end
2454
- ```
2455
-
2456
- 対応する`config.ru`を書きます。
2457
-
2458
- ```ruby
2459
- require './app'
2460
- run Sinatra::Application
2461
- ```
2462
-
2463
- ### config.ruはいつ使うのか?
2464
-
2465
- `config.ru`ファイルは、以下の場合に適しています。
2466
-
2467
- * 異なるRackハンドラ(Passenger, Unicorn, Herokuなど)でデプロイしたいとき
2468
- * `Sinatra::Base`の複数のサブクラスを使いたいとき
2469
- * Sinatraをミドルウェアとして利用し、エンドポイントとしては利用しないとき
2470
-
2471
- **モジュラースタイルに移行したという理由だけで、`config.ru`に移行する必要はなく、`config.ru`で起動するためにモジュラースタイルを使う必要はありません。**
2472
-
2473
- ### Sinatraのミドルウェアとしての利用
2474
-
2475
- Sinatraは他のRackミドルウェアを利用することができるだけでなく、
2476
- 全てのSinatraアプリケーションは、それ自体ミドルウェアとして別のRackエンドポイントの前に追加することが可能です。
2477
-
2478
- このエンドポイントには、別のSinatraアプリケーションまたは他のRackベースのアプリケーション(Rails/Ramaze/Camping/…)が用いられるでしょう。
2479
-
2480
- ```ruby
2481
- require 'sinatra/base'
2482
-
2483
- class LoginScreen < Sinatra::Base
2484
- enable :sessions
2485
-
2486
- get('/login') { haml :login }
2487
-
2488
- post('/login') do
2489
- if params['name'] = 'admin' and params['password'] = 'admin'
2490
- session['user_name'] = params['name']
2491
- else
2492
- redirect '/login'
2493
- end
2494
- end
2495
- end
2496
-
2497
- class MyApp < Sinatra::Base
2498
- # ミドルウェアはbeforeフィルタの前に実行される
2499
- use LoginScreen
2500
-
2501
- before do
2502
- unless session['user_name']
2503
- halt "アクセスは拒否されました。<a href='/login'>ログイン</a>してください。"
2504
- end
2505
- end
2506
-
2507
- get('/') { "Hello #{session['user_name']}." }
2508
- end
2509
- ```
2510
-
2511
- ### 動的なアプリケーションの生成
2512
-
2513
- 新しいアプリケーションを実行時に、定数に割り当てることなく生成したくなる場合があるでしょう。`Sinatra.new`を使えばそれができます。
2514
-
2515
- ```ruby
2516
- require 'sinatra/base'
2517
- my_app = Sinatra.new { get('/') { "hi" } }
2518
- my_app.run!
2519
- ```
2520
-
2521
- これは省略できる引数として、それが継承するアプリケーションを取ります。
2522
-
2523
- ```ruby
2524
- # config.ru (rackupで起動)
2525
- require 'sinatra/base'
2526
-
2527
- controller = Sinatra.new do
2528
- enable :logging
2529
- helpers MyHelpers
2530
- end
2531
-
2532
- map('/a') do
2533
- run Sinatra.new(controller) { get('/') { 'a' } }
2534
- end
2535
-
2536
- map('/b') do
2537
- run Sinatra.new(controller) { get('/') { 'b' } }
2538
- end
2539
- ```
2540
-
2541
- これは特にSinatraのextensionをテストするときや、Sinatraを自身のライブラリで利用する場合に役立ちます。
2542
-
2543
- これはまた、Sinatraをミドルウェアとして利用することを極めて簡単にします。
2544
-
2545
- ```ruby
2546
- require 'sinatra/base'
2547
-
2548
- use Sinatra do
2549
- get('/') { ... }
2550
- end
2551
-
2552
- run RailsProject::Application
2553
- ```
2554
-
2555
- ## スコープとバインディング(Scopes and Binding)
2556
-
2557
- 現在のスコープはどのメソッドや変数が利用可能かを決定します。
2558
-
2559
- ### アプリケーション/クラスのスコープ
2560
-
2561
- 全てのSinatraアプリケーションはSinatra::Baseのサブクラスに相当します。
2562
- もしトップレベルDSLを利用しているならば(`require 'sinatra'`)このクラスはSinatra::Applicationであり、
2563
- そうでなければ、あなたが明示的に作成したサブクラスです。
2564
- クラスレベルでは`get`や`before`のようなメソッドを持っています。
2565
- しかし`request`や`session`オブジェクトには、全てのリクエストに対する単一のアプリケーションクラスがあるだけなので、アクセスできません。
2566
-
2567
- `set`によって作られたオプションはクラスレベルのメソッドです。
2568
-
2569
- ```ruby
2570
- class MyApp < Sinatra::Base
2571
- # アプリケーションスコープの中だよ!
2572
- set :foo, 42
2573
- foo # => 42
2574
-
2575
- get '/foo' do
2576
- # もうアプリケーションスコープの中にいないよ!
2577
- end
2578
- end
2579
- ```
2580
-
2581
- 次の場所ではアプリケーションスコープバインディングを持ちます。
2582
-
2583
- * アプリケーションクラス本体
2584
- * 拡張によって定義されたメソッド
2585
- * `helpers`に渡されたブロック
2586
- * `set`の値として使われるProcまたはブロック
2587
- * `Sinatra.new`に渡されたブロック
2588
-
2589
- このスコープオブジェクト(クラス)は次のように利用できます。
2590
-
2591
- * configureブロックに渡されたオブジェクト経由(`configure { |c| ... }`)
2592
- * リクエストスコープの中での`settings`
2593
-
2594
- ### リクエスト/インスタンスのスコープ
2595
-
2596
- やってくるリクエストごとに、あなたのアプリケーションクラスの新しいインスタンスが作成され、全てのハンドラブロックがそのスコープで実行されます。
2597
- このスコープの内側からは`request`や`session`オブジェクトにアクセスすることができ、`erb`や`haml`のようなレンダリングメソッドを呼び出すことができます。
2598
- リクエストスコープの内側からは、`settings`ヘルパーによってアプリケーションスコープにアクセスすることができます。
2599
-
2600
- ```ruby
2601
- class MyApp < Sinatra::Base
2602
- # アプリケーションスコープの中だよ!
2603
- get '/define_route/:name' do
2604
- # '/define_route/:name'のためのリクエストスコープ
2605
- @value = 42
2606
-
2607
- settings.get("/#{params['name']}") do
2608
- # "/#{params['name']}"のためのリクエストスコープ
2609
- @value # => nil (not the same request)
2610
- end
2611
-
2612
- "ルーティングが定義された!"
2613
- end
2614
- end
2615
- ```
2616
-
2617
- 次の場所ではリクエストスコープバインディングを持ちます。
2618
-
2619
- * get/head/post/put/delete/options/patch/link/unlink ブロック
2620
- * before/after フィルタ
2621
- * helper メソッド
2622
- * テンプレート/ビュー
2623
-
2624
- ### デリゲートスコープ
2625
-
2626
- デリゲートスコープは、単にクラススコープにメソッドを転送します。
2627
- しかしながら、クラスのバインディングを持っていないため、クラススコープと全く同じふるまいをするわけではありません。
2628
- 委譲すると明示的に示されたメソッドのみが利用可能であり、またクラススコープと変数/状態を共有することはできません(注:
2629
- 異なった`self`を持っています)。
2630
- `Sinatra::Delegator.delegate :method_name`を呼び出すことによってデリゲートするメソッドを明示的に追加することができます。
2631
-
2632
- 次の場所ではデリゲートスコープを持ちます。
2633
-
2634
- * もし`require "sinatra"`しているならば、トップレベルバインディング
2635
- * `Sinatra::Delegator` mixinでextendされたオブジェクト
2636
-
2637
- コードをご覧ください: ここでは [Sinatra::Delegator
2638
- mixin](https://github.com/sinatra/sinatra/blob/ca06364/lib/sinatra/base.rb#L1609-1633)は[mainオブジェクトにextendされています](https://github.com/sinatra/sinatra/blob/ca06364/lib/sinatra/main.rb#L28-30)。
2639
-
2640
- ## コマンドライン
2641
-
2642
- Sinatraアプリケーションは直接実行できます。
2643
-
2644
- ```shell
2645
- ruby myapp.rb [-h] [-x] [-e ENVIRONMENT] [-p PORT] [-o HOST] [-s HANDLER]
2646
- ```
2647
-
2648
- オプション:
2649
-
2650
- ```
2651
- -h # ヘルプ
2652
- -p # ポート指定(デフォルトは4567)
2653
- -o # ホスト指定(デフォルトは0.0.0.0)
2654
- -e # 環境を指定 (デフォルトはdevelopment)
2655
- -s # rackserver/handlerを指定 (デフォルトはpuma)
2656
- -x # mutex lockを付ける (デフォルトはoff)
2657
- ```
2658
-
2659
- ### マルチスレッド
2660
-
2661
- _この[StackOverflow](https://stackoverflow.com/a/6282999/5245129)
2662
- のKonstantinによる回答を言い換えています。_
2663
-
2664
- Sinatraでは同時実行モデルを負わせることはできませんが、根本的な部分であるやPuma、WEBrickのようなRackハンドラ(サーバー)部分に委ねることができます。
2665
- Sinatra自身はスレッドセーフであり、もしRackハンドラが同時実行モデルのスレッドを使用していても問題はありません。
2666
- つまり、これはサーバーを起動させる時、特定のRackハンドラに対して正しい起動処理を特定することが出来ます。
2667
- この例はRainbowsサーバーをマルチスレッドで起動する方法のデモです。
2668
-
2669
- ```ruby
2670
- # config.ru
2671
-
2672
- require 'sinatra/base'
2673
-
2674
- class App < Sinatra::Base
2675
- get '/' do
2676
- "Hello, World"
2677
- end
2678
- end
2679
-
2680
- run App
2681
- ```
2682
-
2683
- ```ruby
2684
- # rainbows.conf
2685
-
2686
- # RainbowsのコンフィギュレータはUnicornのものをベースにしています。
2687
- Rainbows! do
2688
- use :ThreadSpawn
2689
- end
2690
- ```
2691
-
2692
- 次のようなコマンドでサーバを起動します。
2693
-
2694
- ```
2695
- rainbows -c rainbows.conf
2696
- ```
2697
-
2698
- ## 必要環境
2699
-
2700
- 次のRubyバージョンが公式にサポートされています。
2701
-
2702
- <dl>
2703
- <dt>Ruby 1.8.7</dt>
2704
- <dd>
2705
- 1.8.7は完全にサポートされていますが、特にそれでなければならないという理由がないのであれば、アップグレードまたはJRubyまたはRubiniusへの移行を薦めます。1.8.7のサポートがSinatra 2.0の前に終わることはないでしょう。Ruby 1.8.6はサポート対象外です。
2706
- </dd>
2707
-
2708
- <dt>Ruby 1.9.2</dt>
2709
- <dd>
2710
- 1.9.2は完全にサポートされています。1.9.2p0は、Sinatraを起動したときにセグメントフォルトを引き起こすことが分かっているので、使わないでください。公式なサポートは、少なくともSinatra 1.5のリリースまでは続きます。
2711
- </dd>
2712
-
2713
- <dt>Ruby 1.9.3</dt>
2714
- <dd>
2715
- 1.9.3は完全にサポート、そして推奨されています。以前のバージョンからの1.9.3への移行は全セッションを無効にする点、覚えておいてください。
2716
- </dd>
2717
-
2718
- <dt>Ruby 2.0.0</dt>
2719
- <dd>
2720
- 2.0.0は完全にサポート、そして推奨されています。現在、その公式サポートを終了する計画はありません。
2721
- </dd>
2722
-
2723
- <dt>Rubinius</dt>
2724
- <dd>
2725
- Rubiniusは公式にサポートされています(Rubinius >= 2.x)。
2726
- <tt>gem install puma</tt>することが推奨されています。
2727
- </dd>
2728
-
2729
- <dt>JRuby</dt>
2730
- <dd>
2731
- JRubyの最新安定版が公式にサポートされています。JRubyでC拡張を使うことは推奨されていません。
2732
- <tt>gem install trinidad</tt>することが推奨されています。
2733
- </dd>
2734
- </dl>
2735
-
2736
- 開発チームは常に最新となるRubyバージョンに注視しています。
2737
-
2738
- 次のRuby実装は公式にはサポートされていませんが、Sinatraが起動すると報告されています。
2739
-
2740
- * JRubyとRubiniusの古いバージョン
2741
- * Ruby Enterprise Edition
2742
- * MacRuby, Maglev, IronRuby
2743
- * Ruby 1.9.0と1.9.1 (これらの使用はお薦めしません)
2744
-
2745
- 公式サポートをしないという意味は、問題がそこだけで起こり、サポートされているプラットフォーム上では起きない場合に、開発チームはそれはこちら側の問題ではないとみなすということです。
2746
-
2747
- 開発チームはまた、ruby-head(最新となる2.1.0)に対しCIを実行していますが、それが一貫して動くようになるまで何も保証しません。2.1.0が完全にサポートされればその限りではありません。
2748
-
2749
- Sinatraは、利用するRuby実装がサポートしているオペレーティングシステム上なら動作するはずです。
2750
-
2751
- MacRubyを使う場合は、`gem install control_tower`してください。
2752
-
2753
- Sinatraは現在、Cardinal、SmallRuby、BlueRubyまたは1.8.7以前のバージョンのRuby上では動作しません。
2754
-
2755
- ## 最新開発版
2756
-
2757
- Sinatraの最新開発版のコードを使いたい場合は、マスターブランチに対してアプリケーションを走らせて構いません。ある程度安定しています。また、適宜プレリリース版gemをpushしているので、
2758
-
2759
- ```shell
2760
- gem install sinatra --pre
2761
- ```
2762
-
2763
- すれば、最新の機能のいくつかを利用できます。
2764
-
2765
- ### Bundlerを使う場合
2766
-
2767
- 最新のSinatraでアプリケーションを動作させたい場合には、[Bundler](https://bundler.io)を使うのがお薦めのやり方です。
2768
-
2769
- まず、Bundlerがなければそれをインストールします。
2770
-
2771
- ```shell
2772
- gem install bundler
2773
- ```
2774
-
2775
- そして、プロジェクトのディレクトリで、`Gemfile`を作ります。
2776
-
2777
- ```ruby
2778
- source 'https://rubygems.org'
2779
- gem 'sinatra', :github => "sinatra/sinatra"
2780
-
2781
- # 他の依存ライブラリ
2782
- gem 'haml' # Hamlを使う場合
2783
- gem 'activerecord', '~> 3.0' # ActiveRecord 3.xが必要かもしれません
2784
- ```
2785
-
2786
- ノート: `Gemfile`にアプリケーションの依存ライブラリのすべてを並べる必要があります。しかし、Sinatraが直接依存するもの(RackおよびTile)はBundlerによって自動的に取り込まれ、追加されます。
2787
-
2788
- これで、以下のようにしてアプリケーションを起動することができます。
2789
-
2790
- ```shell
2791
- bundle exec ruby myapp.rb
2792
- ```
2793
-
2794
- ### 直接組み込む場合
2795
-
2796
- ローカルにクローンを作って、`sinatra/lib`ディレクトリを`$LOAD_PATH`に追加してアプリケーションを起動します。
2797
-
2798
- ```shell
2799
- cd myapp
2800
- git clone git://github.com/sinatra/sinatra.git
2801
- ruby -I sinatra/lib myapp.rb
2802
- ```
2803
-
2804
- 追ってSinatraのソースを更新する方法。
2805
-
2806
- ```shell
2807
- cd myapp/sinatra
2808
- git pull
2809
- ```
2810
-
2811
- ### グローバル環境にインストールする場合
2812
-
2813
- Sinatraのgemを自身でビルドすることもできます。
2814
-
2815
- ```shell
2816
- git clone git://github.com/sinatra/sinatra.git
2817
- cd sinatra
2818
- rake sinatra.gemspec
2819
- rake install
2820
- ```
2821
-
2822
- gemをルートとしてインストールする場合は、最後のステップはこうなります。
2823
-
2824
- ```shell
2825
- sudo rake install
2826
- ```
2827
-
2828
- ## バージョニング(Versioning)
2829
-
2830
- Sinatraは、[Semantic Versioning](https://semver.org/)におけるSemVerおよびSemVerTagの両方に準拠しています。
2831
-
2832
- ## 参考文献
2833
-
2834
- * [プロジェクトサイト](http://www.sinatrarb.com/) - ドキュメント、ニュース、他のリソースへのリンクがあります。
2835
- * [プロジェクトに参加(貢献)する](http://www.sinatrarb.com/contributing.html) - バグレポート パッチの送信、サポートなど
2836
- * [Issue tracker](https://github.com/sinatra/sinatra/issues)
2837
- * [Twitter](https://twitter.com/sinatra)
2838
- * [メーリングリスト](https://groups.google.com/group/sinatrarb/topics)
2839
- * http://freenode.net上のIRC: [#sinatra](irc://chat.freenode.net/#sinatra)
2840
- * [Sinatra Book](https://github.com/sinatra/sinatra-book/) クックブック、チュートリアル
2841
- * [Sinatra Recipes](http://recipes.sinatrarb.com/) コミュニティによるレシピ集
2842
- * http://www.rubydoc.info/上のAPIドキュメント: [最新版(latest release)用](http://www.rubydoc.info/gems/sinatra)または[現在のHEAD用](http://www.rubydoc.info/github/sinatra/sinatra)
2843
- * [CIサーバ](https://travis-ci.org/sinatra/sinatra)
2844
- * [Greenbear Laboratory Rack日本語マニュアル](http://route477.net/w/RackReferenceJa.html)