sinatra-acd 1.4.5

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