sinatra 1.1.0 → 1.1.2

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

Potentially problematic release.


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

@@ -859,7 +859,7 @@ application (Rails/Ramaze/Camping/...).
859
859
  require 'sinatra/base'
860
860
 
861
861
  class LoginScreen < Sinatra::Base
862
- enable :session
862
+ enable :sessions
863
863
 
864
864
  get('/login') { haml :login }
865
865
 
@@ -901,7 +901,7 @@ for all requests.
901
901
 
902
902
  Options created via `set` are methods at class level:
903
903
 
904
- class MyApp << Sinatra::Base
904
+ class MyApp < Sinatra::Base
905
905
  # Hey, I'm in the application scope!
906
906
  set :foo, 42
907
907
  foo # => 42
@@ -931,7 +931,7 @@ can access the `request` and `session` object or call rendering methods like
931
931
  `erb` or `haml`. You can access the application scope from within the request
932
932
  scope via the `settings` helper:
933
933
 
934
- class MyApp << Sinatra::Base
934
+ class MyApp < Sinatra::Base
935
935
  # Hey, I'm in the application scope!
936
936
  get '/define_route/:name' do
937
937
  # Request scope for '/define_route/:name'
@@ -0,0 +1,1015 @@
1
+ = Sinatra
2
+ <i>Внимание: Этот документ является переводом Английской версии и может быть устаревшим</i>
3
+
4
+ Sinatra — это предметно-ориентированный язык (DSL) для быстрого создания приложений на Ruby с
5
+ приложением минимума усилий:
6
+
7
+ # myapp.rb
8
+ require 'sinatra'
9
+
10
+ get '/' do
11
+ 'Hello world!'
12
+ end
13
+
14
+ Установите gem и запустите приложение с помощью:
15
+
16
+ gem install sinatra
17
+ ruby -rubygems myapp.rb
18
+
19
+ Результат будет тут: http://localhost:4567
20
+
21
+ == Маршруты
22
+
23
+ В Sinatra маршрут — это пара: HTTP метод и шаблон (образец) URL.
24
+ Каждый маршрут ассоциирован с блоком:
25
+
26
+ get '/' do
27
+ .. что-то показать ..
28
+ end
29
+
30
+ post '/' do
31
+ .. что-то создать ..
32
+ end
33
+
34
+ put '/' do
35
+ .. что-то обновить ..
36
+ end
37
+
38
+ delete '/' do
39
+ .. что-то удалить ..
40
+ end
41
+
42
+ Маршруты сверяются с запросом по очередности определения. Первый же совпавший с запросом маршрут и будет вызван.
43
+
44
+ Шаблоны маршрутов могут включать в себя параметры доступные в
45
+ <tt>params</tt> xэше:
46
+
47
+ get '/hello/:name' do
48
+ # соответствует "GET /hello/foo" и "GET /hello/bar",
49
+ # где params[:name] 'foo' или 'bar'
50
+ "Hello #{params[:name]}!"
51
+ end
52
+
53
+ Можно также использовать именные параметры в переменных блоков:
54
+
55
+ get '/hello/:name' do |n|
56
+ "Hello #{n}!"
57
+ end
58
+
59
+ Шаблоны маршрутов также могут включать splat (wildcard, *, любая строка символов) параметры доступные
60
+ в <tt>params[:splat]</tt> массиве.
61
+
62
+ get '/say/*/to/*' do
63
+ # соответствует /say/hello/to/world
64
+ params[:splat] # => ["hello", "world"]
65
+ end
66
+
67
+ get '/download/*.*' do
68
+ # соответствует /download/path/to/file.xml
69
+ params[:splat] # => ["path/to/file", "xml"]
70
+ end
71
+
72
+ Маршруты также могут использовать регулярные выражения в качестве шаблона URL:
73
+
74
+ get %r{/hello/([\w]+)} do
75
+ "Hello, #{params[:captures].first}!"
76
+ end
77
+
78
+ Или с параметром блока:
79
+
80
+ get %r{/hello/([\w]+)} do |c|
81
+ "Hello, #{c}!"
82
+ end
83
+
84
+ === Условия
85
+
86
+ Маршруты могут включать различные условия совпадений, такие как user agent:
87
+
88
+ get '/foo', :agent => /Songbird (\d\.\d)[\d\/]*?/ do
89
+ "You're using Songbird version #{params[:agent][0]}"
90
+ end
91
+
92
+ get '/foo' do
93
+ # соответствует с non-songbird браузерам
94
+ end
95
+
96
+ Другими доступными условиями являются +host_name+ и +provides+:
97
+
98
+ get '/', :host_name => /^admin\./ do
99
+ "Admin Area, Access denied!"
100
+ end
101
+
102
+ get '/', :provides => 'html' do
103
+ haml :index
104
+ end
105
+
106
+ get '/', :provides => ['rss', 'atom', 'xml'] do
107
+ builder :feed
108
+ end
109
+
110
+ Довольно легко можно задать собственные условия:
111
+
112
+ set(:probability) { |value| condition { rand <= value } }
113
+
114
+ get '/win_a_car', :probability => 0.1 do
115
+ "You won!"
116
+ end
117
+
118
+ get '/win_a_car' do
119
+ "Sorry, you lost."
120
+ end
121
+
122
+ === Возвращаемые значения
123
+
124
+ Возвращаемое значение блока маршрута ограничивается телом ответа, которое будет передано HTTP клиенту,
125
+ или следующей подпрограммой (middleware) в Rack стеке. Чаще всего это строка, как в вышеизложенных примерах.
126
+ Но и другие значения также приемлемы.
127
+
128
+ Вы можете вернуть любой объект, который будет либо корректным Rack ответом, Rack
129
+ телом ответа, либо кодом состояния HTTP:
130
+
131
+ * Массив с тремя переменными: <tt>[status (Fixnum), headers (Hash), response body (должен отвечать на #each)]</tt>
132
+ * Массив с двумя переменными: <tt>[status (Fixnum), response body (должен отвечать на #each)]</tt>
133
+ * Объект, отвечающий на <tt>#each</tt>, который передает только строковые типы данных в этот блок
134
+ * Fixnum, соответствующий коду состояния HTTP
135
+
136
+ Таким образом мы легко можем создать поточный пример:
137
+
138
+ class Stream
139
+ def each
140
+ 100.times { |i| yield "#{i}\n" }
141
+ end
142
+ end
143
+
144
+ get('/') { Stream.new }
145
+
146
+ == Статические файлы
147
+
148
+ Статические файлы отдаются из <tt>./public</tt> директории. Вы можете указать другое место,
149
+ используя <tt>:public</tt> опцию:
150
+
151
+ set :public, File.dirname(__FILE__) + '/static'
152
+
153
+ Учтите, что имя директории со статическими файлами не включено в URL. Например, файл
154
+ <tt>./public/css/style.css</tt> будет доступен как
155
+ <tt>http://example.com/css/style.css</tt>.
156
+
157
+ == Виды / Шаблоны
158
+
159
+ Шаблоны по умолчанию будут использованы из директории <tt>./views</tt>.
160
+ Для использования другой директории:
161
+
162
+ set :views, File.dirname(__FILE__) + '/templates'
163
+
164
+ Важно помнить, что вы всегда должны указывать шаблоны
165
+ с помощью символов, даже если это подкаталог (в этом случае
166
+ используйте <tt>:'subdir/template'</tt>). Вы должны использовать
167
+ символ, иначе методы, ответственные за рендеринг, отобразят просто переданную им строку.
168
+
169
+ === Haml шаблоны
170
+
171
+ Haml gem/библиотека необходима для рендеринга HAML шаблонов:
172
+
173
+ ## Вам нужно будет подключить haml gem в приложении
174
+ require 'haml'
175
+
176
+ get '/' do
177
+ haml :index
178
+ end
179
+
180
+ Отрисует <tt>./views/index.haml</tt>.
181
+
182
+ {Опции Haml}[http://haml-lang.com/docs/yardoc/file.HAML_REFERENCE.html#options]
183
+ могут быть установлены глобально через конфигурацию Sinatra,
184
+ см. {Опции и Конфигурация}[http://www.sinatrarb.com/configuration.html],
185
+ и переопределены локально.
186
+
187
+ set :haml, :format => :html5 # :xhtml - Haml формат по умолчанию
188
+
189
+ get '/' do
190
+ haml :index, :format => :html4 # переопределен
191
+ end
192
+
193
+
194
+ === Erb шаблоны
195
+
196
+ ## Вам нужно будет подключить erb в приложении
197
+ require 'erb'
198
+
199
+ get '/' do
200
+ erb :index
201
+ end
202
+
203
+ Отрисует <tt>./views/index.erb</tt>
204
+
205
+ === Erubis шаблоны
206
+
207
+ Erubis gem/библиотека необходима для рендеринга erubis шаблонов:
208
+
209
+ ## Вам нужно будет подключить erubis в приложении
210
+ require 'erubis'
211
+
212
+ get '/' do
213
+ erubis :index
214
+ end
215
+
216
+ Отрисует <tt>./views/index.erubis</tt>
217
+
218
+ === Builder шаблоны
219
+
220
+ Builder gem/библиотека необходима для рендеринга builder шаблонов:
221
+
222
+ ## Вам нужно будет подключить builder в приложении
223
+ require 'builder'
224
+
225
+ get '/' do
226
+ builder :index
227
+ end
228
+
229
+ Отрисует <tt>./views/index.builder</tt>.
230
+
231
+ === Nokogiri шаблоны
232
+
233
+ Nokogiri gem/библиотека необходима для рендеринга nokogiri шаблонов:
234
+
235
+ ## Вам нужно будет подключить nokogiri в приложении
236
+ require 'nokogiri'
237
+
238
+ get '/' do
239
+ nokogiri :index
240
+ end
241
+
242
+ Отрисует <tt>./views/index.nokogiri</tt>.
243
+
244
+ === Sass шаблоны
245
+
246
+ Haml gem/библиотека необходима для рендеринга Sass шаблонов:
247
+
248
+ ## Вам нужно будет подключить haml или sass в приложении
249
+ require 'sass'
250
+
251
+ get '/stylesheet.css' do
252
+ sass :stylesheet
253
+ end
254
+
255
+ Отрисует <tt>./views/stylesheet.sass</tt>.
256
+
257
+ {Опции Sass}[http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#options]
258
+ могут быть установлены глобально через конфигурацию Sinatra,
259
+ см. {Опции и Конфигурация}[http://www.sinatrarb.com/configuration.html],
260
+ и переопределены локально.
261
+
262
+ set :sass, :style => :compact # :nested - стиль Sass по умолчанию
263
+
264
+ get '/stylesheet.css' do
265
+ sass :stylesheet, :style => :expanded # переопределен
266
+ end
267
+
268
+ === Scss шаблоны
269
+
270
+ Haml gem/библиотека необходима для рендеринга Scss шаблонов:
271
+
272
+ ## Вам нужно будет подключить haml или sass в приложении
273
+ require 'sass'
274
+
275
+ get '/stylesheet.css' do
276
+ scss :stylesheet
277
+ end
278
+
279
+ Отрисует <tt>./views/stylesheet.scss</tt>.
280
+
281
+ {Опции Scss}[http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#options]
282
+ могут быть установлены глобально через конфигурацию Sinatra,
283
+ см. {Опции и Конфигурация}[http://www.sinatrarb.com/configuration.html],
284
+ и переопределены локально.
285
+
286
+ set :scss, :style => :compact # :nested - стиль Scss по умолчанию
287
+
288
+ get '/stylesheet.css' do
289
+ scss :stylesheet, :style => :expanded # переопределен
290
+ end
291
+
292
+ === Less шаблоны
293
+
294
+ less gem/библиотека необходима для рендеринга Less шаблонов:
295
+
296
+ ## Вам нужно будет подключить less в приложении
297
+ require 'less'
298
+
299
+ get '/stylesheet.css' do
300
+ less :stylesheet
301
+ end
302
+
303
+ Отрисует <tt>./views/stylesheet.less</tt>.
304
+
305
+ === Liquid шаблоны
306
+
307
+ liquid gem/библиотека необходима для рендеринга liquid шаблонов:
308
+
309
+ ## Вам нужно будет подключить liquid в приложении
310
+ require 'liquid'
311
+
312
+ get '/' do
313
+ liquid :index
314
+ end
315
+
316
+ Отрисует <tt>./views/index.liquid</tt>.
317
+
318
+ Так как в Liquid шаблонах невозможно вызывать методы из Ruby (кроме +yield+),
319
+ то вы почти всегда будете передавать локальные переменные:
320
+
321
+ liquid :index, :locals => { :key => 'value' }
322
+
323
+ === Markdown шаблоны
324
+
325
+ rdiscount gem/библиотека необходима для рендеринга Markdown шаблонов:
326
+
327
+ ## Вам нужно будет подключить rdiscount в приложении
328
+ require "rdiscount"
329
+
330
+ get '/' do
331
+ markdown :index
332
+ end
333
+
334
+ Отрисует <tt>./views/index.markdown</tt> (+md+ и +mkd+ также являются допустимыми файловыми
335
+ расширениями).
336
+
337
+ В markdown невозможно вызывать методы или передавать локальные переменные. Следовательно, вам скорее всего придется
338
+ использовать этот шаблон совместно с другим движком рендеринга:
339
+
340
+ erb :overview, :locals => { :text => markdown(:introduction) }
341
+
342
+ Заметьте, что вы можете вызывать метод markdown из других шаблонов:
343
+
344
+ %h1 Hello From Haml!
345
+ %p= markdown(:greetings)
346
+
347
+ === Textile шаблоны
348
+
349
+ RedCloth gem/библиотека необходима для рендеринга Textile шаблонов:
350
+
351
+ ## Вам нужно будет подключить redcloth в приложении
352
+ require "redcloth"
353
+
354
+ get '/' do
355
+ textile :index
356
+ end
357
+
358
+ Отрисует <tt>./views/index.textile</tt>.
359
+
360
+ В textile невозможно вызывать методы или передавать локальные переменные. Следовательно, вам скорее всего придется
361
+ использовать этот шаблон совместно с другим движком рендеринга:
362
+
363
+ erb :overview, :locals => { :text => textile(:introduction) }
364
+
365
+ Заметьте, что вы можете вызывать метод textile из других шаблонов:
366
+
367
+ %h1 Hello From Haml!
368
+ %p= textile(:greetings)
369
+
370
+ === RDoc шаблоны
371
+
372
+ RDoc gem/библиотека необходима для рендеринга RDoc шаблонов:
373
+
374
+ ## Вам нужно будет подключить rdoc в приложении
375
+ require "rdoc"
376
+
377
+ get '/' do
378
+ rdoc :index
379
+ end
380
+
381
+ Отрисует <tt>./views/index.rdoc</tt>.
382
+
383
+ В rdoc невозможно вызывать методы или передавать локальные переменные. Следовательно, вам скорее всего придется
384
+ использовать этот шаблон совместно с другим движком рендеринга:
385
+
386
+ erb :overview, :locals => { :text => rdoc(:introduction) }
387
+
388
+ Заметьте, что вы можете вызывать метод rdoc из других шаблонов:
389
+
390
+ %h1 Hello From Haml!
391
+ %p= rdoc(:greetings)
392
+
393
+ === Radius шаблоны
394
+
395
+ radius gem/библиотека необходима для рендеринга Radius шаблонов:
396
+
397
+ ## Вам нужно будет подключить radius в приложении
398
+ require 'radius'
399
+
400
+ get '/' do
401
+ radius :index
402
+ end
403
+
404
+ Отрисует <tt>./views/index.radius</tt>.
405
+
406
+ Так как в Radius шаблоне невозможно вызывать методы из Ruby (кроме +yield+),
407
+ то вы почти всегда будете передавать локальные переменные:
408
+
409
+ radius :index, :locals => { :key => 'value' }
410
+
411
+ === Markaby шаблоны
412
+
413
+ markaby gem/библиотека необходима для рендеринга Markaby шаблонов:
414
+
415
+ ## Вам нужно будет подключить markaby в приложении
416
+ require 'markaby'
417
+
418
+ get '/' do
419
+ markaby :index
420
+ end
421
+
422
+ Отрисует <tt>./views/index.mab</tt>.
423
+
424
+ === CoffeeScript шаблоны
425
+
426
+ coffee-script gem/библиотека и `coffee` бинарный файл необходимы для рендеринга CoffeeScript шаблонов:
427
+
428
+ ## Вам нужно будет подключить coffee-script в приложении
429
+ require 'coffee-script'
430
+
431
+ get '/application.js' do
432
+ coffee :application
433
+ end
434
+
435
+ Отрисует <tt>./views/application.coffee</tt>.
436
+
437
+ === Внутристроковые шаблоны
438
+
439
+ get '/' do
440
+ haml '%div.title Hello World'
441
+ end
442
+
443
+ Отрисует внутристроковый шаблон.
444
+
445
+ === Доступ к переменным в шаблонах
446
+
447
+ Шаблоны интерпретируются в том же контексте, что и обработчики маршрутов. Переменные экзмепляра,
448
+ установленные в процесе обработки маршрутов, будут доступны напрямую в шаблонах:
449
+
450
+ get '/:id' do
451
+ @foo = Foo.find(params[:id])
452
+ haml '%h1= @foo.name'
453
+ end
454
+
455
+ Либо установите их через хеш локальных переменных:
456
+
457
+ get '/:id' do
458
+ foo = Foo.find(params[:id])
459
+ haml '%h1= foo.name', :locals => { :foo => foo }
460
+ end
461
+
462
+ Это обычно используется когда шаблоны рендерятся как частные (partials) из других шаблонов.
463
+
464
+ === Вложенные шаблоны
465
+
466
+ Шаблоны также могут быть определены в конце файла-исходника:
467
+
468
+ require 'sinatra'
469
+
470
+ get '/' do
471
+ haml :index
472
+ end
473
+
474
+ __END__
475
+
476
+ @@ layout
477
+ %html
478
+ = yield
479
+
480
+ @@ index
481
+ %div.title Hello world!!!!!
482
+
483
+ Заметьте: Вложенные шаблоны, определенные в файле-исходнике, который подключил sinatra, будут
484
+ автоматически загружены. Вызовите <tt>enable :inline_templates</tt> напрямую, если у вас вложенные
485
+ шаблоны в других файлах.
486
+
487
+ === Именные шаблоны
488
+
489
+ Шаблоны также могут быть определены, используя <tt>template</tt> метод:
490
+
491
+ template :layout do
492
+ "%html\n =yield\n"
493
+ end
494
+
495
+ template :index do
496
+ '%div.title Hello World!'
497
+ end
498
+
499
+ get '/' do
500
+ haml :index
501
+ end
502
+
503
+ Если шаблон с именем "layout" существует, то он будет использован каждый раз,
504
+ когда шаблоны будут отрисовываться. Вы можете отключить layout-шаблон с помощью <tt>:layout => false</tt>.
505
+
506
+ get '/' do
507
+ haml :index, :layout => !request.xhr?
508
+ end
509
+
510
+ == Методы помощники
511
+
512
+ Используйте <tt>helpers</tt> метод для определения методов помощников для дальнейшего
513
+ использования в обработчиках маршрутов и шаблонах:
514
+
515
+ helpers do
516
+ def bar(name)
517
+ "#{name}bar"
518
+ end
519
+ end
520
+
521
+ get '/:name' do
522
+ bar(params[:name])
523
+ end
524
+
525
+ == Фильтры
526
+
527
+ Before-фильтры выполняются перед каждым запросом в том же контексте, что и маршруты. Фильтры могут изменять
528
+ как запрос, так и ответ на него. Переменные экземпляра, установленные в фильтрах, доступны в маршрутах и шаблонах:
529
+
530
+ before do
531
+ @note = 'Hi!'
532
+ request.path_info = '/foo/bar/baz'
533
+ end
534
+
535
+ get '/foo/*' do
536
+ @note #=> 'Hi!'
537
+ params[:splat] #=> 'bar/baz'
538
+ end
539
+
540
+ After-фильтры выполняются после каждого запроса в том же контексте, что и пути. Фильтры могут изменять
541
+ как запрос, так и ответ на него. Переменные экземпляра, установленные в before-фильтрах и маршрутах, будут доступны в after-фильтрах:
542
+
543
+ after do
544
+ puts response.status
545
+ end
546
+
547
+ Фильтры могут использовать шаблоны URL и будут интерпретированы, только если путь запроса совпадет с этим шаблоном:
548
+
549
+ before '/protected/*' do
550
+ authenticate!
551
+ end
552
+
553
+ after '/create/:slug' do |slug|
554
+ session[:last_slug] = slug
555
+ end
556
+
557
+ == Прерывание
558
+
559
+ Чтобы незамедлительно прервать обработку запроса внутри фильтра или маршрута, используйте:
560
+
561
+ halt
562
+
563
+ Можно также указать статус при прерывании:
564
+
565
+ halt 410
566
+
567
+ Тело:
568
+
569
+ halt 'this will be the body'
570
+
571
+ И то, и другое:
572
+
573
+ halt 401, 'go away!'
574
+
575
+ Можно указать заголовки:
576
+
577
+ halt 402, {'Content-Type' => 'text/plain'}, 'revenge'
578
+
579
+ == Передача
580
+
581
+ Маршрут может передать обработку запроса следующему совпадающему маршруту, используя <tt>pass</tt>:
582
+
583
+ get '/guess/:who' do
584
+ pass unless params[:who] == 'Frank'
585
+ 'You got me!'
586
+ end
587
+
588
+ get '/guess/*' do
589
+ 'You missed!'
590
+ end
591
+
592
+ Блок маршрута сразу же прерывается, и контроль переходит к следующему совпадающему маршруту.
593
+ Если соответствующий маршрут не найден, то ответом на запрос будет 404.
594
+
595
+ == Доспут к объекту запроса
596
+
597
+ Объект входящего запроса доступен на уровне обработки запроса (в фильтрах, маршрутах, обработчиках ошибок)
598
+ с помощью `request` метода:
599
+
600
+ # приложение запущено на http://example.com/example
601
+ get '/foo' do
602
+ request.body # тело запроса, посланное клиентом (см. ниже)
603
+ request.scheme # "http"
604
+ request.script_name # "/example"
605
+ request.path_info # "/foo"
606
+ request.port # 80
607
+ request.request_method # "GET"
608
+ request.query_string # ""
609
+ request.content_length # длина тела запроса
610
+ request.media_type # медиа тип тела запроса
611
+ request.host # "example.com"
612
+ request.get? # true (для других участвующих HTTP глаголов есть похожие методы)
613
+ request.form_data? # false
614
+ request["SOME_HEADER"] # значение SOME_HEADER заголовка
615
+ request.referer # источник запроса клиента либо '/'
616
+ request.user_agent # user agent (используется для :agent условия)
617
+ request.cookies # хеш куки браузера
618
+ request.xhr? # является ли запрос ajax запросом?
619
+ request.url # "http://example.com/example/foo"
620
+ request.path # "/example/foo"
621
+ request.ip # IP адрес клиента
622
+ request.secure? # false
623
+ request.env # env хеш как получено Rack
624
+ end
625
+
626
+ Некоторые опции, такие как <tt>script_name</tt> или <tt>path_info</tt> могут быть переписаны:
627
+
628
+ before { request.path_info = "/" }
629
+
630
+ get "/" do
631
+ "all requests end up here"
632
+ end
633
+
634
+ <tt>request.body</tt> является IO или StringIO объектом:
635
+
636
+ post "/api" do
637
+ request.body.rewind # в случае, если кто-то уже прочитал тело запроса
638
+ data = JSON.parse request.body.read
639
+ "Hello #{data['name']}!"
640
+ end
641
+
642
+ == Конфигурация
643
+
644
+ Этот блок исполняется один раз при старте в любом окружении, режиме (environment):
645
+
646
+ configure do
647
+ ...
648
+ end
649
+
650
+ Будет запущено, когда окружение (RACK_ENV переменная) установлена в
651
+ <tt>:production</tt>:
652
+
653
+ configure :production do
654
+ ...
655
+ end
656
+
657
+ Будет запущено, когда окружение <tt>:production</tt> или <tt>:test</tt>:
658
+
659
+ configure :production, :test do
660
+ ...
661
+ end
662
+
663
+ == Обработка ошибок
664
+
665
+ Обработчики ошибок исполняются в том же контексте, что и маршруты, before-фильтры, а это означает, что всякие
666
+ прелести вроде <tt>haml</tt>, <tt>erb</tt>, <tt>halt</tt> и т.д. доступны и им.
667
+
668
+ ===  NotFound
669
+
670
+ Когда возбуждено исключение <tt>Sinatra::NotFound</tt>, или кодом ответа является 404,
671
+ то будет вызван <tt>not_found</tt> обработчик:
672
+
673
+ not_found do
674
+ 'This is nowhere to be found.'
675
+ end
676
+
677
+ === Ошибки
678
+
679
+ Обработчик ошибок +error+ будет вызван, когда исключение возбуждено из блока маршрута, либо из фильтра.
680
+ Объект-исключение доступен как переменная <tt>sinatra.error</tt> в Rack:
681
+
682
+ error do
683
+ 'Sorry there was a nasty error - ' + env['sinatra.error'].name
684
+ end
685
+
686
+ Частные ошибки:
687
+
688
+ error MyCustomError do
689
+ 'So what happened was...' + request.env['sinatra.error'].message
690
+ end
691
+
692
+ Тогда, если это произошло:
693
+
694
+ get '/' do
695
+ raise MyCustomError, 'something bad'
696
+ end
697
+
698
+ То вы получите:
699
+
700
+ So what happened was... something bad
701
+
702
+ Также вы можете установить обработчик ошибок для кода состояния HTTP:
703
+
704
+ error 403 do
705
+ 'Access forbidden'
706
+ end
707
+
708
+ get '/secret' do
709
+ 403
710
+ end
711
+
712
+ Либо набора кодов:
713
+
714
+ error 400..510 do
715
+ 'Boom'
716
+ end
717
+
718
+ Sinatra устанавливает специальные <tt>not_found</tt> и <tt>error</tt> обработчики, когда запущена в режиме
719
+ разработки (окружение <tt>:development</tt>).
720
+
721
+ == Mime типы
722
+
723
+ Когда вы используете <tt>send_file</tt> или статические файлы, у вас могут быть mime типы, которые Sinatra
724
+ не понимает по умолчанию. Используйте +mime_type+ для их регистрации по расширению файла:
725
+
726
+ mime_type :foo, 'text/foo'
727
+
728
+ Вы также можете использовать это в +content_type+ помощнике:
729
+
730
+ content_type :foo
731
+
732
+ == Rack подпрограммы
733
+
734
+ Sinatra использует Rack[http://rack.rubyforge.org/], минимальный стандартный
735
+ интерфейс для веб-фреймворков на Ruby. Одной из самых интересных для разработчиков возможностей Rack
736
+ является поддержка подпрограмм ("middleware") -- компонентов,
737
+ "сидящих" между сервером и вашим приложением, которые отслеживают и/или манипулируют
738
+ HTTP запросами/ответами для предоставления различной функциональности.
739
+
740
+ В Sinatra очень просто использовать такие Rack подпрограммы с помощью метода +use+:
741
+
742
+ require 'sinatra'
743
+ require 'my_custom_middleware'
744
+
745
+ use Rack::Lint
746
+ use MyCustomMiddleware
747
+
748
+ get '/hello' do
749
+ 'Hello World'
750
+ end
751
+
752
+ Семантика +use+ идентична той, что определена для
753
+ Rack::Builder[http://rack.rubyforge.org/doc/classes/Rack/Builder.html] DSL
754
+ (чаще всего используется в rackup файлах). Например, +use+ метод принимает
755
+ множественные переменные, также как и блоки:
756
+
757
+ use Rack::Auth::Basic do |username, password|
758
+ username == 'admin' && password == 'secret'
759
+ end
760
+
761
+ Rack распространяется с различными стандартными подпрограммами
762
+ для логирования, отладки, маршрутизации URL, аутентификации, обработки сессий. Sinatra использует
763
+ многие из этих компонентов автоматически, основываясь на конфигурации, чтобы вам не приходилось
764
+ регистрировать/использовать (+use+) их вручную.
765
+
766
+ == Тестирование
767
+
768
+ Тесты для Sinatra приложений могут быть написаны с помощью библиотек, фреймворков, поддерживающих
769
+ тестирование Rack. {Rack::Test}[http://gitrdoc.com/brynary/rack-test] рекомендован:
770
+
771
+ require 'my_sinatra_app'
772
+ require 'test/unit'
773
+ require 'rack/test'
774
+
775
+ class MyAppTest < Test::Unit::TestCase
776
+ include Rack::Test::Methods
777
+
778
+ def app
779
+ Sinatra::Application
780
+ end
781
+
782
+ def test_my_default
783
+ get '/'
784
+ assert_equal 'Hello World!', last_response.body
785
+ end
786
+
787
+ def test_with_params
788
+ get '/meet', :name => 'Frank'
789
+ assert_equal 'Hello Frank!', last_response.body
790
+ end
791
+
792
+ def test_with_rack_env
793
+ get '/', {}, 'HTTP_USER_AGENT' => 'Songbird'
794
+ assert_equal "You're using Songbird!", last_response.body
795
+ end
796
+ end
797
+
798
+ Заметьте: Встроенные модули Sinatra::Test и Sinatra::TestHarness являются
799
+ устаревшими, начиная с 0.9.2 релиза.
800
+
801
+ == Sinatra::Base - Подпрограммы, библиотеки и модульные приложения
802
+
803
+ Описание своего приложения самым простейшим способом (с помощью DSL верхнего уровня, как в примерах выше)
804
+ работает отлично для крохотных приложений, но имеет множество недостатков, когда надо
805
+ создать компоненты, такие как Rack
806
+ middleware, Rails metal, простые библиотеки с серверными компонентами,
807
+ Sinatra расширения.
808
+ DSL верхнего уровня загрязняет пространство имен <tt>Object</tt> и подразумевает стиль конфигурации
809
+ микро-приложения (например, единый файл приложения, ./public и
810
+ ./views директории, создание логов, страницу деталей об исключениях
811
+ и т.д.). И тут на помощь приходит Sinatra::Base:
812
+
813
+ require 'sinatra/base'
814
+
815
+ class MyApp < Sinatra::Base
816
+ set :sessions, true
817
+ set :foo, 'bar'
818
+
819
+ get '/' do
820
+ 'Hello world!'
821
+ end
822
+ end
823
+
824
+ MyApp класс является независимым Rack компонентом, который может исполнять роли
825
+ Rack подпрограммы, Rack приложения, Rails metal. Вы можете +use+ (использовать) или
826
+ +run+ (запустить) этот класс из rackup файла +config.ru+; или контролировать серверную
827
+ часть из библиотеки:
828
+
829
+ MyApp.run! :host => 'localhost', :port => 9090
830
+
831
+ Методы, доступные Sinatra::Base сабклассам идентичны тем, что доступны
832
+ в DSL верхнего уровня. Большинство приложений верхнего уровня могут быть
833
+ конвертированы в Sinatra::Base компоненты с помощью двух модификаций:
834
+
835
+ * Вы должны подключать +sinatra/base+ вместо +sinatra+,
836
+ иначе все методы предоставляемые Sinatra будут импортированные в глобальное пространство имен.
837
+ * Поместите все маршруты, обработчики ошибок, фильтры и опции в сабкласс Sinatra::Base.
838
+
839
+ <tt>Sinatra::Base</tt> — это чистый лист. Большинство опций, включая встроенный сервер, по умолчанию отключены.
840
+ Смотрите {Опции и Конфигурация}[http://www.sinatrarb.com/configuration.html] для детальной информации
841
+ об опциях и их поведении.
842
+
843
+ === Использование Sinatra как подпрограммы
844
+
845
+ Не только сама Sinatra может использовать подпрограммы Rack, любое Sinatra приложение
846
+ само может быть добавлено к любому Rack эндпоинту в качестве подпрограммы. Этим эндпоинтом
847
+ может быть другое Sinatra приложение, или приложение, основанное на Rack (Rails/Ramaze/Camping/...).
848
+
849
+ require 'sinatra/base'
850
+
851
+ class LoginScreen < Sinatra::Base
852
+ enable :sessions
853
+
854
+ get('/login') { haml :login }
855
+
856
+ post('/login') do
857
+ if params[:name] = 'admin' and params[:password] = 'admin'
858
+ session['user_name'] = params[:name]
859
+ else
860
+ redirect '/login'
861
+ end
862
+ end
863
+ end
864
+
865
+ class MyApp < Sinatra::Base
866
+ # подпрограмма будет запущена перед фильтрами
867
+ use LoginScreen
868
+
869
+ before do
870
+ unless session['user_name']
871
+ halt "Access denied, please <a href='/login'>login</a>."
872
+ end
873
+ end
874
+
875
+ get('/') { "Hello #{session['user_name']}." }
876
+ end
877
+
878
+ == Области видимости и привязка
879
+
880
+ Текущая область видимости определяет методы и переменные, доступные
881
+ в данный момент.
882
+
883
+ === Область видимости приложения / класса
884
+
885
+ Любое Sinatra приложение соответствует сабклассу Sinatra::Base. Если вы
886
+ используете DSL верхнего
887
+ уровня (<tt>require 'sinatra'</tt>), то этим классом будет
888
+ Sinatra::Application, иначе это будет сабкласс, который вы создали вручную.
889
+ На уровне класса вам будут доступны такие методы, как `get` или `before`, но вы
890
+ не сможете иметь доступ к объектам `request` или `session`, так как существует
891
+ только единый класс приложения для всех запросов.
892
+
893
+ Опции, созданные с помощью `set`, являются методами уровня класса:
894
+
895
+ class MyApp < Sinatra::Base
896
+ # Я в области видимости приложения!
897
+ set :foo, 42
898
+ foo # => 42
899
+
900
+ get '/foo' do
901
+ # Я больше не в области видимости приложения!
902
+ end
903
+ end
904
+
905
+ У вас будет область видимости приложения внутри:
906
+
907
+ * Тела вашего класса приложения
908
+ * Методов, определенных расширениями
909
+ * Блока, переданного в `helpers`
910
+ * Блоков, использованных как значения для `set`
911
+
912
+ Вы можете получить доступ к объекту области видимости (классу приложения) следующими способами:
913
+
914
+ * объект, переданный блокам конфигурации (<tt>configure { |c| ... }</tt>)
915
+ * `settings` внутри области видимости запроса
916
+
917
+ === Область видимости запроса/экземпляра
918
+
919
+ Для каждого входящего запроса будет создан новый экземпляр вашего приложения,
920
+ и все блоки обработчика будут запущены в этом контексте. В этой области
921
+ видимости вам доступны `request` и `session` объекты, вызовы методов
922
+ рендеринга, такие как `erb` или `haml`. Вы можете получить доступ к
923
+ области видимости приложения из контекста запроса, используя помощник `settings`:
924
+
925
+ class MyApp < Sinatra::Base
926
+ # Я в области видимости приложения!
927
+ get '/define_route/:name' do
928
+ # Область видимости запроса '/define_route/:name'
929
+ @value = 42
930
+
931
+ settings.get("/#{params[:name]}") do
932
+ # Область видимости запроса "/#{params[:name]}"
933
+ @value # => nil (другой запрос)
934
+ end
935
+
936
+ "Route defined!"
937
+ end
938
+ end
939
+
940
+ У вас будет область видимости запроса внутри:
941
+
942
+ * get/head/post/put/delete блоков
943
+ * before/after фильтрах
944
+ * методах помощниках
945
+ * шаблонах/видах
946
+
947
+ === Область видимости делегирования
948
+
949
+ Область видимости делегирования просто перенаправляет методы в область видимости класса.
950
+ Однако, оно не полностью на 100% ведет себя как область видимости класса,
951
+ так как у вас нету привязки к классу: только методы, явно помеченные для
952
+ делегирования, будут доступны, а переменных/состояний области видимости класса
953
+ не будет (иначе говоря, у вас будет другой `self` объект). Вы можете
954
+ непосредственно добавить методы делегирования, используя
955
+ <tt>Sinatra::Delegator.delegate :method_name</tt>.
956
+
957
+ У вас будет контекст делегирования внутри:
958
+
959
+ * Привязки верхнего уровня, если вы сделали <tt>require "sinatra"</tt>
960
+ * Объекта, расширенного с помощью примеси `Sinatra::Delegator`
961
+
962
+ Посмотрите сами в код: тут
963
+ {Sinatra::Delegator примесь}[http://github.com/sinatra/sinatra/blob/ceac46f0bc129a6e994a06100aa854f606fe5992/lib/sinatra/base.rb#L1128]
964
+ будет {включена в глобальное пространство имен}[http://github.com/sinatra/sinatra/blob/ceac46f0bc129a6e994a06100aa854f606fe5992/lib/sinatra/main.rb#L28].
965
+
966
+ == Командная строка
967
+
968
+ Sinatra приложения могут быть запущены напрямую:
969
+
970
+ ruby myapp.rb [-h] [-x] [-e ENVIRONMENT] [-p PORT] [-o HOST] [-s HANDLER]
971
+
972
+ Опции включают:
973
+
974
+ -h # помощь
975
+ -p # настроить порт (по умолчанию 4567)
976
+ -o # настроить хост (по умолчанию 0.0.0.0)
977
+ -e # настроить окружение, режим (по умолчанию development)
978
+ -s # настроить rack сервер/обработчик (по умолчанию thin)
979
+ -x # включить мьютекс (по умолчанию выключен)
980
+
981
+ == На острие
982
+
983
+ Если вы хотите использовать новейший код Sinatra, то создайте локальный
984
+ клон и запускайте свое приложение с <tt>sinatra/lib</tt> директорией
985
+ в <tt>LOAD_PATH</tt>:
986
+
987
+ cd myapp
988
+ git clone git://github.com/sinatra/sinatra.git
989
+ ruby -Isinatra/lib myapp.rb
990
+
991
+ Также вы можете добавить <tt>sinatra/lib</tt> директорию в
992
+ <tt>LOAD_PATH</tt> приложения:
993
+
994
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/sinatra/lib'
995
+ require 'rubygems'
996
+ require 'sinatra'
997
+
998
+ get '/about' do
999
+ "I'm running version " + Sinatra::VERSION
1000
+ end
1001
+
1002
+ Чтобы обновить исходники Sinatra:
1003
+
1004
+ cd myproject/sinatra
1005
+ git pull
1006
+
1007
+ == Больше информации
1008
+
1009
+ * {Вебсайт проекта}[http://www.sinatrarb.com/] - Дополнительная документация,
1010
+ новости и ссылки на другие ресурсы.
1011
+ * {Участие}[http://www.sinatrarb.com/contributing] - Нашли баг? Нужна помощь? Написали патч?
1012
+ * {Слежение за проблемами}[http://github.com/sinatra/sinatra/issues]
1013
+ * {Twitter}[http://twitter.com/sinatra]
1014
+ * {Лист рассылки}[http://groups.google.com/group/sinatrarb/topics]
1015
+ * {IRC: #sinatra}[irc://chat.freenode.net/#sinatra] on http://freenode.net