sinatra 1.2.9 → 1.3.0.a
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of sinatra might be problematic. Click here for more details.
- data/CHANGES +12 -118
- data/Gemfile +23 -37
- data/LICENSE +1 -1
- data/README.de.rdoc +11 -15
- data/README.es.rdoc +50 -76
- data/README.fr.rdoc +7 -7
- data/README.hu.rdoc +1 -1
- data/README.jp.rdoc +2 -8
- data/README.pt-br.rdoc +1 -1
- data/README.pt-pt.rdoc +1 -1
- data/README.rdoc +64 -139
- data/README.ru.rdoc +618 -68
- data/README.zh.rdoc +7 -7
- data/Rakefile +6 -29
- data/lib/sinatra.rb +3 -0
- data/lib/sinatra/base.rb +115 -179
- data/lib/sinatra/main.rb +1 -1
- data/lib/sinatra/rack.rb +44 -0
- data/lib/sinatra/showexceptions.rb +3 -3
- data/sinatra.gemspec +5 -4
- data/test/coffee_test.rb +11 -15
- data/test/delegator_test.rb +3 -43
- data/test/helper.rb +0 -4
- data/test/helpers_test.rb +44 -37
- data/test/nokogiri_test.rb +6 -5
- data/test/result_test.rb +4 -4
- data/test/routing_test.rb +8 -132
- data/test/server_test.rb +2 -3
- data/test/settings_test.rb +0 -26
- data/test/slim_test.rb +25 -15
- data/test/static_test.rb +1 -0
- metadata +17 -67
- data/test/rack_test.rb +0 -45
data/README.ru.rdoc
CHANGED
@@ -18,6 +18,9 @@ Sinatra — это предметно-ориентированный язык (D
|
|
18
18
|
|
19
19
|
Результат будет тут: http://localhost:4567
|
20
20
|
|
21
|
+
Рекомендуется также запустить <tt>gem install thin</tt>, чтобы Sinatra
|
22
|
+
могла использовать thin в качестве сервера.
|
23
|
+
|
21
24
|
== Маршруты
|
22
25
|
|
23
26
|
В Sinatra маршрут — это пара: HTTP метод и шаблон (образец) URL.
|
@@ -32,7 +35,11 @@ Sinatra — это предметно-ориентированный язык (D
|
|
32
35
|
end
|
33
36
|
|
34
37
|
put '/' do
|
35
|
-
.. что-то
|
38
|
+
.. что-то заменить ..
|
39
|
+
end
|
40
|
+
|
41
|
+
patch '/' do
|
42
|
+
.. что-то изменить ..
|
36
43
|
end
|
37
44
|
|
38
45
|
delete '/' do
|
@@ -61,7 +68,7 @@ Sinatra — это предметно-ориентированный язык (D
|
|
61
68
|
end
|
62
69
|
|
63
70
|
Шаблоны маршрутов также могут включать splat (wildcard, *, любая строка символов) параметры доступные
|
64
|
-
в <tt>params[:splat]</tt>
|
71
|
+
в <tt>params[:splat]</tt> массиве:
|
65
72
|
|
66
73
|
get '/say/*/to/*' do
|
67
74
|
# соответствует /say/hello/to/world
|
@@ -147,6 +154,47 @@ Sinatra — это предметно-ориентированный язык (D
|
|
147
154
|
|
148
155
|
get('/') { Stream.new }
|
149
156
|
|
157
|
+
=== Собственные детекторы совпадений для маршрутов
|
158
|
+
|
159
|
+
Как показано выше, Sinatra поставляется со встроенной поддержкой строк и
|
160
|
+
регулярных выражений как шаблонов URL. Но и это еще не все. Вы можете
|
161
|
+
легко определить свои собственные детекторы совпадений (matchers) для маршрутов:
|
162
|
+
|
163
|
+
class AllButPattern
|
164
|
+
Match = Struct.new(:captures)
|
165
|
+
|
166
|
+
def initialize(except)
|
167
|
+
@except = except
|
168
|
+
@captures = Match.new([])
|
169
|
+
end
|
170
|
+
|
171
|
+
def match(str)
|
172
|
+
@captures unless @except === str
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def all_but(pattern)
|
177
|
+
AllButPattern.new(pattern)
|
178
|
+
end
|
179
|
+
|
180
|
+
get all_but("/index") do
|
181
|
+
# ...
|
182
|
+
end
|
183
|
+
|
184
|
+
Заметьте, что предыдущий пример довольно переусложнен, ведь он также может
|
185
|
+
быть записан в следующем виде:
|
186
|
+
|
187
|
+
get // do
|
188
|
+
pass if request.path_info == "/index"
|
189
|
+
# ...
|
190
|
+
end
|
191
|
+
|
192
|
+
Или с использованием негативного просмотра вперед:
|
193
|
+
|
194
|
+
get %r{^(?!/index$)} do
|
195
|
+
# ...
|
196
|
+
end
|
197
|
+
|
150
198
|
== Статические файлы
|
151
199
|
|
152
200
|
Статические файлы отдаются из <tt>./public</tt> директории. Вы можете указать другое место,
|
@@ -362,7 +410,7 @@ Sinatra — это предметно-ориентированный язык (D
|
|
362
410
|
|
363
411
|
Вы не можете вызывать Ruby из Markdown, соответственно, вы не можете использовать
|
364
412
|
лэйаут-шаблоны (layouts) на Markdown. Тем не менее, есть возможность использовать один
|
365
|
-
движок рендеринга для шаблона, а другой для лэйаута с помощью опции
|
413
|
+
движок рендеринга для шаблона, а другой для лэйаута с помощью опции <tt>:layout_engine</tt>:
|
366
414
|
|
367
415
|
get '/' do
|
368
416
|
markdown :index, :layout_engine => :erb
|
@@ -421,7 +469,7 @@ Sinatra — это предметно-ориентированный язык (D
|
|
421
469
|
|
422
470
|
Вы не можете вызывать Ruby из Textile, соответственно, вы не можете использовать
|
423
471
|
лэйаут-шаблоны на Textile. Тем не менее, есть возможность использовать один
|
424
|
-
движок рендеринга для шаблона, а другой для лэйаута с помощью опции
|
472
|
+
движок рендеринга для шаблона, а другой для лэйаута с помощью опции <tt>:layout_engine</tt>:
|
425
473
|
|
426
474
|
get '/' do
|
427
475
|
textile :index, :layout_engine => :erb
|
@@ -466,7 +514,7 @@ Sinatra — это предметно-ориентированный язык (D
|
|
466
514
|
|
467
515
|
Вы не можете вызывать Ruby из RDoc, соответственно, вы не можете использовать
|
468
516
|
лэйаут-шаблоны на RDoc. Тем не менее, есть возможность использовать один
|
469
|
-
движок рендеринга для шаблона, а другой для лэйаута с помощью опции
|
517
|
+
движок рендеринга для шаблона, а другой для лэйаута с помощью опции <tt>:layout_engine</tt>:
|
470
518
|
|
471
519
|
get '/' do
|
472
520
|
rdoc :index, :layout_engine => :erb
|
@@ -604,7 +652,7 @@ Sinatra — это предметно-ориентированный язык (D
|
|
604
652
|
@@ index
|
605
653
|
%div.title Hello world!!!!!
|
606
654
|
|
607
|
-
Заметьте:
|
655
|
+
Заметьте: вложенные шаблоны, определенные в файле-исходнике, который подключил Sinatra, будут
|
608
656
|
автоматически загружены. Вызовите <tt>enable :inline_templates</tt> напрямую, если у вас вложенные
|
609
657
|
шаблоны в других файлах.
|
610
658
|
|
@@ -626,7 +674,7 @@ Sinatra — это предметно-ориентированный язык (D
|
|
626
674
|
|
627
675
|
Если шаблон с именем "layout" существует, то он будет использован каждый раз,
|
628
676
|
когда шаблоны будут отрисовываться. Вы можете отключать лэйаут в каждом конкретном случае с помощью
|
629
|
-
<tt>:layout => false</tt> или отключить его для всего приложения, например, так: <tt>set :haml, :layout => false</tt
|
677
|
+
<tt>:layout => false</tt> или отключить его для всего приложения, например, так: <tt>set :haml, :layout => false</tt>:
|
630
678
|
|
631
679
|
get '/' do
|
632
680
|
haml :index, :layout => !request.xhr?
|
@@ -657,24 +705,9 @@ Sinatra — это предметно-ориентированный язык (D
|
|
657
705
|
Отрисует <tt>./views/index.myat</tt>. Чтобы узнать больше о Tilt,
|
658
706
|
смотрите https://github.com/rtomayko/tilt
|
659
707
|
|
660
|
-
== Методы-помощники
|
661
|
-
|
662
|
-
Используйте метод <tt>helpers</tt>, чтобы определить методы-помощники, которые
|
663
|
-
в дальнейшем можно будет использовать в обработчиках маршрутов и шаблонах:
|
664
|
-
|
665
|
-
helpers do
|
666
|
-
def bar(name)
|
667
|
-
"#{name}bar"
|
668
|
-
end
|
669
|
-
end
|
670
|
-
|
671
|
-
get '/:name' do
|
672
|
-
bar(params[:name])
|
673
|
-
end
|
674
|
-
|
675
708
|
== Фильтры
|
676
709
|
|
677
|
-
|
710
|
+
+before+-фильтры выполняются перед каждым запросом в том же контексте, что и маршруты. Фильтры могут изменять
|
678
711
|
как запрос, так и ответ на него. Переменные экземпляра, установленные в фильтрах, доступны в маршрутах и шаблонах:
|
679
712
|
|
680
713
|
before do
|
@@ -687,13 +720,17 @@ Before-фильтры выполняются перед каждым запро
|
|
687
720
|
params[:splat] #=> 'bar/baz'
|
688
721
|
end
|
689
722
|
|
690
|
-
|
691
|
-
как запрос, так и ответ на него. Переменные экземпляра, установленные в before
|
723
|
+
+after+-фильтры выполняются после каждого запроса в том же контексте, что и пути. Фильтры могут изменять
|
724
|
+
как запрос, так и ответ на него. Переменные экземпляра, установленные в +before+-фильтрах и маршрутах,
|
725
|
+
будут доступны в +after+-фильтрах:
|
692
726
|
|
693
727
|
after do
|
694
728
|
puts response.status
|
695
729
|
end
|
696
730
|
|
731
|
+
Заметьте: если вы используете метод +body+, а не просто возвращаете строку из
|
732
|
+
маршрута, то тело ответа не будет доступно в +after+-фильтрах, потому что оно будет сгенерировано позднее.
|
733
|
+
|
697
734
|
Фильтры могут использовать шаблоны URL и будут интерпретированы, только если путь запроса совпадет с этим шаблоном:
|
698
735
|
|
699
736
|
before '/protected/*' do
|
@@ -714,7 +751,67 @@ After-фильтры выполняются после каждого запро
|
|
714
751
|
# ...
|
715
752
|
end
|
716
753
|
|
717
|
-
==
|
754
|
+
== Методы-помощники
|
755
|
+
|
756
|
+
Используйте метод <tt>helpers</tt>, чтобы определить методы-помощники, которые
|
757
|
+
в дальнейшем можно будет использовать в обработчиках маршрутов и шаблонах:
|
758
|
+
|
759
|
+
helpers do
|
760
|
+
def bar(name)
|
761
|
+
"#{name}bar"
|
762
|
+
end
|
763
|
+
end
|
764
|
+
|
765
|
+
get '/:name' do
|
766
|
+
bar(params[:name])
|
767
|
+
end
|
768
|
+
|
769
|
+
=== Использование сессий
|
770
|
+
|
771
|
+
Сессия используется, чтобы сохранять состояние между запросами. Если эта опция
|
772
|
+
включена, то у вас будет один хэш сессии на одну пользовательскую сессию:
|
773
|
+
|
774
|
+
enable :sessions
|
775
|
+
|
776
|
+
get '/' do
|
777
|
+
"value = " << session[:value].inspect
|
778
|
+
end
|
779
|
+
|
780
|
+
get '/:value' do
|
781
|
+
session[:value] = params[:value]
|
782
|
+
end
|
783
|
+
|
784
|
+
Заметьте, что при использовании <tt>enable :sessions</tt> все данные
|
785
|
+
сохраняются в куки. Это может быть не совсем то, что вы хотите (например,
|
786
|
+
сохранение больших объемов данных увеличит ваш трафик). В таком случае вы
|
787
|
+
можете использовать альтернативную Rack "прослойку" (middleware), реализующую
|
788
|
+
механизм сессий. Для этого *не надо* вызывать <tt>enable :sessions</tt>,
|
789
|
+
вместо этого следует подключить ее также как и любую другую "прослойку":
|
790
|
+
|
791
|
+
use Rack::Session::Pool, :expire_after => 2592000
|
792
|
+
|
793
|
+
get '/' do
|
794
|
+
"value = " << session[:value].inspect
|
795
|
+
end
|
796
|
+
|
797
|
+
get '/:value' do
|
798
|
+
session[:value] = params[:value]
|
799
|
+
end
|
800
|
+
|
801
|
+
Для повышения безопасности данные сессии в куках подписываются секретным
|
802
|
+
ключом. Секретный ключ генерируется Sinatra. Тем не менее, так как этот
|
803
|
+
ключ будет меняться с каждым запуском приложения, вы, возможно, захотите
|
804
|
+
установить ключ вручную, чтобы у всех экземпляров вашего приложения
|
805
|
+
быд один и тот же ключ:
|
806
|
+
|
807
|
+
set :session_secret, 'super secret'
|
808
|
+
|
809
|
+
Если вы хотите больше настроек для сессий, вы можете задать их, используя
|
810
|
+
хэш с опциями и параметр +sessions+:
|
811
|
+
|
812
|
+
set :sessions, :domain => 'foo.com'
|
813
|
+
|
814
|
+
=== Прерывание
|
718
815
|
|
719
816
|
Чтобы незамедлительно прервать обработку запроса внутри фильтра или маршрута, используйте:
|
720
817
|
|
@@ -736,7 +833,11 @@ After-фильтры выполняются после каждого запро
|
|
736
833
|
|
737
834
|
halt 402, {'Content-Type' => 'text/plain'}, 'revenge'
|
738
835
|
|
739
|
-
|
836
|
+
И, конечно, можно использовать шаблоны с +halt+:
|
837
|
+
|
838
|
+
halt erb(:error)
|
839
|
+
|
840
|
+
=== Передача
|
740
841
|
|
741
842
|
Маршрут может передать обработку запроса следующему совпадающему маршруту, используя <tt>pass</tt>:
|
742
843
|
|
@@ -752,10 +853,224 @@ After-фильтры выполняются после каждого запро
|
|
752
853
|
Блок маршрута сразу же прерывается, и контроль переходит к следующему совпадающему маршруту.
|
753
854
|
Если соответствующий маршрут не найден, то ответом на запрос будет 404.
|
754
855
|
|
755
|
-
|
856
|
+
=== Вызов другого маршрута
|
857
|
+
|
858
|
+
Иногда +pass+ не подходит, например, если вы хотите получить результат
|
859
|
+
вызова другого обработчика маршрута. В таком случае просто используйте +call+:
|
860
|
+
|
861
|
+
get '/foo' do
|
862
|
+
status, headers, body = call request.env.merge("PATH_INFO" => '/bar')
|
863
|
+
[status, body.upcase]
|
864
|
+
end
|
865
|
+
|
866
|
+
get '/bar' do
|
867
|
+
"bar"
|
868
|
+
end
|
869
|
+
|
870
|
+
Заметьте, что в предыдущем примере можно облегчить тестирование и повысить
|
871
|
+
производительность, перенеся <tt>"bar"</tt> в метод-помощник, используемый
|
872
|
+
и в <tt>/foo</tt>, и в <tt>/bar</tt>.
|
873
|
+
|
874
|
+
Если вы хотите, чтобы запрос был отправлен в тот же экземпляр приложения, а не
|
875
|
+
в его копию, используйте <tt>call!</tt> вместо <tt>call</tt>.
|
876
|
+
|
877
|
+
Если хотите узнать больше о <tt>call</tt>, смотрите спецификацию Rack.
|
878
|
+
|
879
|
+
=== Задание тела, кода и заголовков ответа
|
880
|
+
|
881
|
+
Хорошим тоном является установка кода состояния HTTP и тела ответа в возвращаемом
|
882
|
+
значении обработчика маршрута. Тем не менее, в некоторых ситуациях вам, возможно,
|
883
|
+
понадобится задать тело ответа в произвольной точке потока исполнения. Вы можете
|
884
|
+
сделать это с помощью метода-помощника +body+. Если вы задействуете метод +body+,
|
885
|
+
то вы можете использовать его и в дальнейшем, чтобы получить доступ к телу ответа.
|
886
|
+
|
887
|
+
get '/foo' do
|
888
|
+
body "bar"
|
889
|
+
end
|
890
|
+
|
891
|
+
after do
|
892
|
+
puts body
|
893
|
+
end
|
894
|
+
|
895
|
+
Также можно передать блок в метод +body+, который затем будет вызван
|
896
|
+
обработчиком Rack (такой подход может быть использован для реализации поточного
|
897
|
+
ответа, см. "Возвращаемые значения").
|
898
|
+
|
899
|
+
Аналогично вы можете установить код ответа и его заголовки:
|
900
|
+
|
901
|
+
get '/foo' do
|
902
|
+
status 418
|
903
|
+
headers \
|
904
|
+
"Allow" => "BREW, POST, GET, PROPFIND, WHEN"
|
905
|
+
"Refresh" => "Refresh: 20; http://www.ietf.org/rfc/rfc2324.txt"
|
906
|
+
body "I'm a tea pot!"
|
907
|
+
end
|
908
|
+
|
909
|
+
Как и +body+, методы +headers+ и +status+, вызванные без аргументов, возвращают
|
910
|
+
свои текущие значения.
|
911
|
+
|
912
|
+
=== Mime-типы
|
913
|
+
|
914
|
+
Когда вы используете <tt>send_file</tt> или статические файлы, у вас могут быть mime-типы, которые Sinatra
|
915
|
+
не понимает по умолчанию. Используйте +mime_type+ для их регистрации по расширению файла:
|
916
|
+
|
917
|
+
mime_type :foo, 'text/foo'
|
918
|
+
|
919
|
+
Вы также можете использовать это в +content_type+ помощнике:
|
920
|
+
|
921
|
+
get '/' do
|
922
|
+
content_type :foo
|
923
|
+
"foo foo foo"
|
924
|
+
end
|
925
|
+
|
926
|
+
=== Генерирование URL
|
927
|
+
|
928
|
+
Чтобы сформировать URL вам следует использовать метод +url+, например, в Haml:
|
929
|
+
|
930
|
+
%a{:href => url('/foo')} foo
|
931
|
+
|
932
|
+
Этот метод учитывает обратные прокси и маршрутизаторы Rack, если они присутствуют.
|
933
|
+
|
934
|
+
Наряду с +url+ вы можете использовать +to+ (смотрите пример ниже).
|
935
|
+
|
936
|
+
=== Перенаправление (редирект)
|
937
|
+
|
938
|
+
Вы можете перенаправить браузер пользователя с помощью метода +redirect+:
|
939
|
+
|
940
|
+
get '/foo' do
|
941
|
+
redirect to('/bar')
|
942
|
+
end
|
943
|
+
|
944
|
+
Любые дополнительные параметры используются по аналогии с аргументами метода +halt+:
|
945
|
+
|
946
|
+
redirect to('/bar'), 303
|
947
|
+
redirect 'http://google.com', 'wrong place, buddy'
|
948
|
+
|
949
|
+
Вы также можете перенаправить пользователя обратно, на страницу с которой он пришел,
|
950
|
+
с помощью <tt>redirect back</tt>:
|
951
|
+
|
952
|
+
get '/foo' do
|
953
|
+
"<a href='/bar'>do something</a>"
|
954
|
+
end
|
955
|
+
|
956
|
+
get '/bar' do
|
957
|
+
do_something
|
958
|
+
redirect back
|
959
|
+
end
|
960
|
+
|
961
|
+
Чтобы передать какие-либо параметры вместе с перенаправлением, либо добавьте их в строку запроса:
|
962
|
+
|
963
|
+
redirect to('/bar?sum=42')
|
964
|
+
|
965
|
+
Либо используйте сессию:
|
966
|
+
|
967
|
+
enable :session
|
968
|
+
|
969
|
+
get '/foo' do
|
970
|
+
session[:secret] = 'foo'
|
971
|
+
redirect to('/bar')
|
972
|
+
end
|
973
|
+
|
974
|
+
get '/bar' do
|
975
|
+
session[:secret]
|
976
|
+
end
|
977
|
+
|
978
|
+
=== Управление кэшированием
|
979
|
+
|
980
|
+
Установка корректных заголовков — основа правильного HTTP кэширования.
|
981
|
+
|
982
|
+
Вы можете легко выставить заголовок Cache-Control таким образом:
|
983
|
+
|
984
|
+
get '/' do
|
985
|
+
cache_control :public
|
986
|
+
"cache it!"
|
987
|
+
end
|
988
|
+
|
989
|
+
Совет: задавайте кэширование в +before+-фильтре:
|
990
|
+
|
991
|
+
before do
|
992
|
+
cache_control :public, :must_revalidate, :max_age => 60
|
993
|
+
end
|
994
|
+
|
995
|
+
Если вы используете метод +expires+ для задания соответствующего заголовка,
|
996
|
+
то <tt>Cache-Control</tt> будет выставлен автоматически:
|
997
|
+
|
998
|
+
before do
|
999
|
+
expires 500, :public, :must_revalidate
|
1000
|
+
end
|
1001
|
+
|
1002
|
+
Чтобы как следует использовать кэши, вам следует подумать об использовании
|
1003
|
+
+etag+ и +last_modified+. Рекомендуется использовать эти методы *до*
|
1004
|
+
выполнения "тяжелых" вычислений, так как они немедленно отправят ответ клиенту,
|
1005
|
+
если текущая версия уже есть в его кэше:
|
1006
|
+
|
1007
|
+
get '/article/:id' do
|
1008
|
+
@article = Article.find params[:id]
|
1009
|
+
last_modified @article.updated_at
|
1010
|
+
etag @article.sha1
|
1011
|
+
erb :article
|
1012
|
+
end
|
1013
|
+
|
1014
|
+
Так же вы можете использовать
|
1015
|
+
{weak ETag}[http://en.wikipedia.org/wiki/HTTP_ETag#Strong_and_weak_validation]:
|
1016
|
+
|
1017
|
+
etag @article.sha1, :weak
|
1018
|
+
|
1019
|
+
Эти методы-помощники не станут ничего кэшировать для вас, но они дадут
|
1020
|
+
необходимую информацию для вашего кэша. Если вы ищите легкое решение для
|
1021
|
+
кэширования, попробуйте {rack-cache}[http://rtomayko.github.com/rack-cache/]:
|
1022
|
+
|
1023
|
+
require "rack/cache"
|
1024
|
+
require "sinatra"
|
1025
|
+
|
1026
|
+
use Rack::Cache
|
1027
|
+
|
1028
|
+
get '/' do
|
1029
|
+
cache_control :public, :max_age => 36000
|
1030
|
+
sleep 5
|
1031
|
+
"hello"
|
1032
|
+
end
|
1033
|
+
|
1034
|
+
=== Отправка файлов
|
1035
|
+
|
1036
|
+
Для отправки файлов пользователю вы можете использовать метод <tt>send_file</tt>:
|
1037
|
+
|
1038
|
+
get '/' do
|
1039
|
+
send_file 'foo.png'
|
1040
|
+
end
|
1041
|
+
|
1042
|
+
Этот метод имеет несколько опций:
|
1043
|
+
|
1044
|
+
send_file 'foo.png', :type => :jpg
|
1045
|
+
|
1046
|
+
Возможные опции:
|
1047
|
+
|
1048
|
+
[filename]
|
1049
|
+
имя файла, по умолчанию: реальное имя файла.
|
1050
|
+
|
1051
|
+
[last_modified]
|
1052
|
+
значение для заголовка Last-Modified, по умолчанию: mtime (время изменения) файла.
|
1053
|
+
|
1054
|
+
[type]
|
1055
|
+
тип файла, по умолчанию: угадывается по расширению файла.
|
1056
|
+
|
1057
|
+
[disposition]
|
1058
|
+
используется для заголовка Content-Disposition, возможные значения:
|
1059
|
+
+nil+ (по умолчанию), <tt>:attachment</tt> и <tt>:inline</tt>.
|
1060
|
+
|
1061
|
+
[length]
|
1062
|
+
значения для заголовка Content-Length, по умолчанию: размер файла.
|
1063
|
+
|
1064
|
+
|
1065
|
+
Этот метод будет использовать возможности Rack сервера для отправки файлов, если они
|
1066
|
+
доступны, а в противном случае, будет напрямую отдавать файл из Ruby процесса.
|
1067
|
+
Метод <tt>send_file</tt> также обеспечивает автоматическую обработку частичных (range)
|
1068
|
+
запросов с помощью Sinatra.
|
756
1069
|
|
757
|
-
|
758
|
-
|
1070
|
+
=== Доспут к объекту запроса
|
1071
|
+
|
1072
|
+
Объект входящего запроса доступен на уровне обработки запроса (в фильтрах, маршрутах,
|
1073
|
+
обработчиках ошибок) с помощью <tt>request</tt> метода:
|
759
1074
|
|
760
1075
|
# приложение запущено на http://example.com/example
|
761
1076
|
get '/foo' do
|
@@ -772,14 +1087,15 @@ After-фильтры выполняются после каждого запро
|
|
772
1087
|
request.get? # true (есть аналоги для других методов HTTP)
|
773
1088
|
request.form_data? # false
|
774
1089
|
request["SOME_HEADER"] # значение заголовка SOME_HEADER
|
775
|
-
request.
|
1090
|
+
request.referrer # источник запроса клиента либо '/'
|
776
1091
|
request.user_agent # user agent (используется для :agent условия)
|
777
1092
|
request.cookies # хеш с куками браузера
|
778
1093
|
request.xhr? # является ли запрос ajax запросом?
|
779
1094
|
request.url # "http://example.com/example/foo"
|
780
1095
|
request.path # "/example/foo"
|
781
1096
|
request.ip # IP-адрес клиента
|
782
|
-
request.secure? # false
|
1097
|
+
request.secure? # false (true, если запрос сделан через SSL)
|
1098
|
+
request.forwarded? # true (если сервер работает за обратным прокси)
|
783
1099
|
request.env # "сырой" env хеш, полученный Rack
|
784
1100
|
end
|
785
1101
|
|
@@ -799,16 +1115,86 @@ After-фильтры выполняются после каждого запро
|
|
799
1115
|
"Hello #{data['name']}!"
|
800
1116
|
end
|
801
1117
|
|
1118
|
+
=== Вложения
|
1119
|
+
|
1120
|
+
Вы можете использовать метод +attachment+, чтобы сказать браузеру, что ответ
|
1121
|
+
сервера должен быть сохранен на диск, а не отображен:
|
1122
|
+
|
1123
|
+
get '/' do
|
1124
|
+
attachment
|
1125
|
+
"store it!"
|
1126
|
+
end
|
1127
|
+
|
1128
|
+
Вы также можете указать и имя файла:
|
1129
|
+
|
1130
|
+
get '/' do
|
1131
|
+
attachment "info.txt"
|
1132
|
+
"store it!"
|
1133
|
+
end
|
1134
|
+
|
1135
|
+
=== Поиск шаблонов
|
1136
|
+
|
1137
|
+
Для поиска шаблонов и их последующего рендеринга используется метод <tt>find_template</tt>:
|
1138
|
+
|
1139
|
+
find_template settings.views, 'foo', Tilt[:haml] do |file|
|
1140
|
+
puts "could be #{file}"
|
1141
|
+
end
|
1142
|
+
|
1143
|
+
Это не очень-то полезный пример. Зато полезен тот факт, что вы можете переопределить
|
1144
|
+
этот метод, чтобы использовать свой собственный механизм поиска. Например, если вы
|
1145
|
+
хотите, чтобы можно было использовать несколько директорий с шаблонами:
|
1146
|
+
|
1147
|
+
set :views, ['views', 'templates']
|
1148
|
+
|
1149
|
+
helpers do
|
1150
|
+
def find_template(views, name, engine, &block)
|
1151
|
+
Array(views).each { |v| super(v, name, engine, &block) }
|
1152
|
+
end
|
1153
|
+
end
|
1154
|
+
|
1155
|
+
Другой пример, в котором используются разные директории для движков рендеринга:
|
1156
|
+
|
1157
|
+
set :views, :sass => 'views/sass', :haml => 'templates', :default => 'views'
|
1158
|
+
|
1159
|
+
helpers do
|
1160
|
+
def find_template(views, name, engine, &block)
|
1161
|
+
_, folder = views.detect { |k,v| engine == Tilt[k] }
|
1162
|
+
folder ||= views[:default]
|
1163
|
+
super(folder, name, engine, &block)
|
1164
|
+
end
|
1165
|
+
end
|
1166
|
+
|
1167
|
+
Вы можете легко вынести этот код в расширение и поделиться им с остальными!
|
1168
|
+
|
1169
|
+
Заметьте, что <tt>find_template</tt не проверяет, существует ли файл на самом деле,
|
1170
|
+
а вызывает заданный блок для всех возможных путей. Дело тут не в производительности,
|
1171
|
+
дело в том, что +render+ вызовет +break+, как только файл не будет найден.
|
1172
|
+
Содержимое и местонахождение шаблонов будет закэшировано, если приложение запущено не
|
1173
|
+
в режиме разработки. Вы должны помнить об этих нюансах, если пишите по-настоящему
|
1174
|
+
сумашедший метод.
|
1175
|
+
|
802
1176
|
== Конфигурация
|
803
1177
|
|
804
1178
|
Этот блок исполняется один раз при старте в любом окружении, режиме (environment):
|
805
1179
|
|
806
1180
|
configure do
|
807
|
-
|
1181
|
+
# задание одной опции
|
1182
|
+
set :option, 'value'
|
1183
|
+
|
1184
|
+
# устанавливаем несколько опций
|
1185
|
+
set :a => 1, :b => 2
|
1186
|
+
|
1187
|
+
# то же самое, что и `set :option, true`
|
1188
|
+
enable :option
|
1189
|
+
|
1190
|
+
# то же самое, что и `set :option, false`
|
1191
|
+
disable :option
|
1192
|
+
|
1193
|
+
# у вас могут быть "динамические" опции с блоками
|
1194
|
+
set(:css_dir) { File.join(views, 'css') }
|
808
1195
|
end
|
809
1196
|
|
810
|
-
Будет запущено, когда окружение (RACK_ENV переменная)
|
811
|
-
<tt>:production</tt>:
|
1197
|
+
Будет запущено, когда окружение (RACK_ENV переменная) <tt>:production</tt>:
|
812
1198
|
|
813
1199
|
configure :production do
|
814
1200
|
...
|
@@ -820,9 +1206,104 @@ After-фильтры выполняются после каждого запро
|
|
820
1206
|
...
|
821
1207
|
end
|
822
1208
|
|
1209
|
+
Вы можете получить доступ к этим опциям с помощью <tt>settings</tt>:
|
1210
|
+
|
1211
|
+
configure do
|
1212
|
+
set :foo, 'bar'
|
1213
|
+
end
|
1214
|
+
|
1215
|
+
get '/' do
|
1216
|
+
settings.foo? # => true
|
1217
|
+
settings.foo # => 'bar'
|
1218
|
+
...
|
1219
|
+
end
|
1220
|
+
|
1221
|
+
=== Доступные настройки
|
1222
|
+
|
1223
|
+
[absolute_redirects] если отключено, то Sinatra будет позволять использование
|
1224
|
+
относительных перенаправлений, тем не менее, Sinatra перестанет
|
1225
|
+
соответствовать RFC 2616 (HTTP 1.1), который разрешает только
|
1226
|
+
абсолютные перенаправления.
|
1227
|
+
|
1228
|
+
Включайте эту опцию, если ваше приложение работает за обратным прокси,
|
1229
|
+
который настроен не совсем корректно. Обратите внимание, метод +url+
|
1230
|
+
все равно будет генерировать абсолютные URL, если вы не передадите
|
1231
|
+
+false+ вторым аргументом.
|
1232
|
+
|
1233
|
+
Отключено по умолчанию.
|
1234
|
+
|
1235
|
+
[add_charsets] mime-типы, к которым метод <tt>content_type</tt> будет автоматически
|
1236
|
+
добавлять информацию о кодировке.
|
1237
|
+
|
1238
|
+
Вам следует добавлять значения к этой опции вместо ее переопределения:
|
1239
|
+
|
1240
|
+
settings.add_charsets << "application/foobar"
|
1241
|
+
|
1242
|
+
[app_file] главный файл приложения, используется для определения корневой директории
|
1243
|
+
проекта, директорий с шаблонами и статическими файлами, вложенных шаблонов.
|
1244
|
+
|
1245
|
+
[bind] используемый IP-адрес (по умолчанию: 0.0.0.0). Используется только
|
1246
|
+
встроенным сервером.
|
1247
|
+
|
1248
|
+
[default_encoding] кодировка, если неизвестна (по умолчанию: <tt>"utf-8"</tt>).
|
1249
|
+
|
1250
|
+
[dump_errors] отображать ошибки в логе.
|
1251
|
+
|
1252
|
+
[environment] текущее окружение, по умолчанию, значение <tt>ENV['RACK_ENV']</tt>
|
1253
|
+
или <tt>"development"</tt>, если <tt>ENV['RACK_ENV']</tt> не доступна.
|
1254
|
+
|
1255
|
+
[logging] использовать логгер.
|
1256
|
+
|
1257
|
+
[lock] создает блокировку для каждого запроса, которая гарантирует обработку
|
1258
|
+
только одного запроса в текущий момент времени в Ruby процессе.
|
1259
|
+
|
1260
|
+
Включайте, если ваше приложение не потоко-безопасно (thread-safe).
|
1261
|
+
Отключено по умолчанию.
|
1262
|
+
|
1263
|
+
[method_override] использовать "магический" параметр <tt>_method</tt>, чтобы позволить
|
1264
|
+
использование PUT/DELETE форм в браузерах, которые не поддерживают
|
1265
|
+
эти методы.
|
1266
|
+
|
1267
|
+
[port] порт, на котором будет работать сервер. Используется только
|
1268
|
+
встроенным сервером.
|
1269
|
+
|
1270
|
+
[prefixed_redirects] добавлять или нет параметр <tt>request.script_name</tt> к редиректам,
|
1271
|
+
если не задан абсолютный путь. Таким образом <tt>redirect '/foo'</tt>
|
1272
|
+
будет вести себя как <tt>redirect to('/foo')</tt>. Отключено по умолчанию.
|
1273
|
+
|
1274
|
+
[public] директория, откуда будут раздаваться статические файлы.
|
1275
|
+
|
1276
|
+
[reload_templates] перезагружать или нет шаблоны на каждый запрос.
|
1277
|
+
Включено в режиме разработки.
|
1278
|
+
|
1279
|
+
[root] корневая директория проекта.
|
1280
|
+
|
1281
|
+
[raise_errors] возбуждать исключения (будет останавливать приложение).
|
1282
|
+
|
1283
|
+
[run] если включено, Sinatra будет самостоятельно запускать веб-сервер.
|
1284
|
+
Не включайте, если используете rackup или аналогичные средства.
|
1285
|
+
|
1286
|
+
[running] работает ли сейчас встроенный сервер?
|
1287
|
+
Не меняйте эту опцию!
|
1288
|
+
|
1289
|
+
[server] сервер или список серверов, которые следует использовать в качестве
|
1290
|
+
встроенного сервера. По умолчанию: ['thin', 'mongrel', 'webrick'],
|
1291
|
+
порядок задает приоритет.
|
1292
|
+
|
1293
|
+
[sessions] включить сессии на основе кук (cookie).
|
1294
|
+
|
1295
|
+
[show_exceptions] показывать стек вызовов (stack trace) в браузере.
|
1296
|
+
|
1297
|
+
[static] должен ли Sinatra осуществлять раздачу статических файлов.
|
1298
|
+
Отключите, когда используете какой-либо веб-сервер для этой цели.
|
1299
|
+
Отключение значительно улучшит производительность приложения.
|
1300
|
+
Включено по умолчанию.
|
1301
|
+
|
1302
|
+
[views] директория с шаблонами.
|
1303
|
+
|
823
1304
|
== Обработка ошибок
|
824
1305
|
|
825
|
-
Обработчики ошибок исполняются в том же контексте, что и маршруты, before
|
1306
|
+
Обработчики ошибок исполняются в том же контексте, что и маршруты, +before+-фильтры, а это означает, что всякие
|
826
1307
|
прелести вроде <tt>haml</tt>, <tt>erb</tt>, <tt>halt</tt> и т.д. доступны и им.
|
827
1308
|
|
828
1309
|
=== NotFound
|
@@ -875,20 +1356,9 @@ After-фильтры выполняются после каждого запро
|
|
875
1356
|
'Boom'
|
876
1357
|
end
|
877
1358
|
|
878
|
-
Sinatra устанавливает специальные <tt>not_found</tt> и <tt>error</tt> обработчики, когда
|
1359
|
+
Sinatra устанавливает специальные <tt>not_found</tt> и <tt>error</tt> обработчики, когда запущен в режиме
|
879
1360
|
разработки (окружение <tt>:development</tt>).
|
880
1361
|
|
881
|
-
== Mime-типы
|
882
|
-
|
883
|
-
Когда вы используете <tt>send_file</tt> или статические файлы, у вас могут быть mime-типы, которые Sinatra
|
884
|
-
не понимает по умолчанию. Используйте +mime_type+ для их регистрации по расширению файла:
|
885
|
-
|
886
|
-
mime_type :foo, 'text/foo'
|
887
|
-
|
888
|
-
Вы также можете использовать это в +content_type+ помощнике:
|
889
|
-
|
890
|
-
content_type :foo
|
891
|
-
|
892
1362
|
== Rack "прослойки"
|
893
1363
|
|
894
1364
|
Sinatra использует Rack[http://rack.rubyforge.org/], минимальный стандартный
|
@@ -984,14 +1454,42 @@ DSL верхнего уровня загрязняет пространство
|
|
984
1454
|
в DSL верхнего уровня. Большинство приложений верхнего уровня могут быть
|
985
1455
|
конвертированы в Sinatra::Base компоненты с помощью двух модификаций:
|
986
1456
|
|
987
|
-
* Вы должны подключать
|
988
|
-
иначе все методы предоставляемые Sinatra будут
|
1457
|
+
* Вы должны подключать <tt>sinatra/base</tt> вместо +sinatra+,
|
1458
|
+
иначе все методы предоставляемые Sinatra будут импортированы в глобальное пространство имен.
|
989
1459
|
* Поместите все маршруты, обработчики ошибок, фильтры и опции в сабкласс Sinatra::Base.
|
990
1460
|
|
991
1461
|
<tt>Sinatra::Base</tt> — это чистый лист. Большинство опций, включая встроенный сервер, по умолчанию отключены.
|
992
1462
|
Смотрите {Опции и Конфигурация}[http://www.sinatrarb.com/configuration.html] для детальной информации
|
993
1463
|
об опциях и их поведении.
|
994
1464
|
|
1465
|
+
=== Модульные приложения против классических
|
1466
|
+
|
1467
|
+
Вопреки всеобщему убеждению в классическом стиле (самом простом) нет ничего плохого.
|
1468
|
+
Если этот стиль подходит вашему приложению, вы не обязаны переписывать его в модульное
|
1469
|
+
приложение.
|
1470
|
+
|
1471
|
+
У классического стиля есть всего два недостатка относительно модульного:
|
1472
|
+
|
1473
|
+
* У вас может быть только одно приложение Sinatra на Ruby процесс. Если вы планируете
|
1474
|
+
использовать больше, то переключайтесь на модульный стиль.
|
1475
|
+
|
1476
|
+
* Приложения, использующие классический стиль, добавляют методы к Object. Если вы
|
1477
|
+
планируете поставлять свое приложение в виде библиотеки/gem, то переключайтесь
|
1478
|
+
на модульный стиль.
|
1479
|
+
|
1480
|
+
Не существует причин, по которым вы не могли бы смешивать модульный и классический стили.
|
1481
|
+
|
1482
|
+
Переходя с одного стиля на другой, примите во внимание следующие изменения в настройках:
|
1483
|
+
|
1484
|
+
Опция Классический Модульный
|
1485
|
+
|
1486
|
+
app_file файл с приложением nil
|
1487
|
+
run $0 == app_file false
|
1488
|
+
logging true false
|
1489
|
+
method_override true false
|
1490
|
+
inline_templates true false
|
1491
|
+
|
1492
|
+
|
995
1493
|
=== Запуск модульных приложений
|
996
1494
|
|
997
1495
|
Есть два общепринятых способа запускать модульные приложения: запуск напрямую с помощью <tt>run!</tt>:
|
@@ -1014,14 +1512,14 @@ DSL верхнего уровня загрязняет пространство
|
|
1014
1512
|
Rack-совместимый сервер приложений.
|
1015
1513
|
|
1016
1514
|
# config.ru
|
1017
|
-
require '
|
1515
|
+
require 'my_app'
|
1018
1516
|
run MyApp
|
1019
1517
|
|
1020
1518
|
Запускаем:
|
1021
1519
|
|
1022
1520
|
rackup -p 4567
|
1023
1521
|
|
1024
|
-
=== Запуск
|
1522
|
+
=== Запуск классических приложений с config.ru
|
1025
1523
|
|
1026
1524
|
Файл приложения:
|
1027
1525
|
|
@@ -1034,7 +1532,7 @@ Rack-совместимый сервер приложений.
|
|
1034
1532
|
|
1035
1533
|
И соответствующий <tt>config.ru</tt>:
|
1036
1534
|
|
1037
|
-
require '
|
1535
|
+
require 'app'
|
1038
1536
|
run Sinatra::Application
|
1039
1537
|
|
1040
1538
|
=== Когда использовать config.ru?
|
@@ -1052,9 +1550,9 @@ Rack-совместимый сервер приложений.
|
|
1052
1550
|
|
1053
1551
|
=== Использование Sinatra в качестве "прослойки"
|
1054
1552
|
|
1055
|
-
Не только
|
1553
|
+
Не только сам Sinatra может использовать "прослойки" Rack, но и любое Sinatra приложение
|
1056
1554
|
само может быть добавлено к любому Rack эндпоинту в качестве "прослойки". Этим эндпоинтом
|
1057
|
-
может быть другое Sinatra приложение, или приложение, основанное на Rack (Rails/Ramaze/Camping/...)
|
1555
|
+
может быть другое Sinatra приложение, или приложение, основанное на Rack (Rails/Ramaze/Camping/...):
|
1058
1556
|
|
1059
1557
|
require 'sinatra/base'
|
1060
1558
|
|
@@ -1096,11 +1594,11 @@ Rack-совместимый сервер приложений.
|
|
1096
1594
|
используете DSL верхнего
|
1097
1595
|
уровня (<tt>require 'sinatra'</tt>), то этим классом будет
|
1098
1596
|
Sinatra::Application, иначе это будет сабкласс, который вы создали вручную.
|
1099
|
-
На уровне класса вам будут доступны такие методы, как
|
1100
|
-
не сможете иметь доступ к объектам
|
1101
|
-
только
|
1597
|
+
На уровне класса вам будут доступны такие методы, как +get+ или +before+, но вы
|
1598
|
+
не сможете иметь доступ к объектам +request+ или +session+, так как существует
|
1599
|
+
только один класс приложения для всех запросов.
|
1102
1600
|
|
1103
|
-
Опции, созданные с помощью
|
1601
|
+
Опции, созданные с помощью +set+, являются методами уровня класса:
|
1104
1602
|
|
1105
1603
|
class MyApp < Sinatra::Base
|
1106
1604
|
# Я в области видимости приложения!
|
@@ -1116,21 +1614,21 @@ Sinatra::Application, иначе это будет сабкласс, котор
|
|
1116
1614
|
|
1117
1615
|
* Тела вашего класса приложения
|
1118
1616
|
* Методов, определенных расширениями
|
1119
|
-
* Блока, переданного в
|
1120
|
-
* Блоков, использованных как значения для
|
1617
|
+
* Блока, переданного в +helpers+
|
1618
|
+
* Блоков, использованных как значения для +set+
|
1121
1619
|
|
1122
1620
|
Вы можете получить доступ к объекту области видимости (классу приложения) следующими способами:
|
1123
1621
|
|
1124
1622
|
* объект, переданный блокам конфигурации (<tt>configure { |c| ... }</tt>)
|
1125
|
-
*
|
1623
|
+
* +settings+ внутри области видимости запроса
|
1126
1624
|
|
1127
1625
|
=== Область видимости запроса/экземпляра
|
1128
1626
|
|
1129
1627
|
Для каждого входящего запроса будет создан новый экземпляр вашего приложения,
|
1130
1628
|
и все блоки обработчика будут запущены в этом контексте. В этой области
|
1131
|
-
видимости вам доступны
|
1132
|
-
рендеринга, такие как
|
1133
|
-
области видимости приложения из контекста запроса, используя помощник
|
1629
|
+
видимости вам доступны +request+ и +session+ объекты, вызовы методов
|
1630
|
+
рендеринга, такие как +erb+ или +haml+. Вы можете получить доступ к
|
1631
|
+
области видимости приложения из контекста запроса, используя помощник +settings+:
|
1134
1632
|
|
1135
1633
|
class MyApp < Sinatra::Base
|
1136
1634
|
# Я в области видимости приложения!
|
@@ -1160,14 +1658,14 @@ Sinatra::Application, иначе это будет сабкласс, котор
|
|
1160
1658
|
Однако, оно не полностью на 100% ведет себя как область видимости класса,
|
1161
1659
|
так как у вас нету привязки к классу: только методы, явно помеченные для
|
1162
1660
|
делегирования, будут доступны, а переменных/состояний области видимости класса
|
1163
|
-
не будет (иначе говоря, у вас будет другой
|
1661
|
+
не будет (иначе говоря, у вас будет другой +self+ объект). Вы можете
|
1164
1662
|
непосредственно добавить методы делегирования, используя
|
1165
1663
|
<tt>Sinatra::Delegator.delegate :method_name</tt>.
|
1166
1664
|
|
1167
1665
|
У вас будет контекст делегирования внутри:
|
1168
1666
|
|
1169
1667
|
* Привязки верхнего уровня, если вы сделали <tt>require "sinatra"</tt>
|
1170
|
-
* Объекта, расширенного с помощью примеси
|
1668
|
+
* Объекта, расширенного с помощью примеси <tt>Sinatra::Delegator</tt>
|
1171
1669
|
|
1172
1670
|
Посмотрите сами в код: тут
|
1173
1671
|
{Sinatra::Delegator примесь}[http://github.com/sinatra/sinatra/blob/ceac46f0bc129a6e994a06100aa854f606fe5992/lib/sinatra/base.rb#L1128]
|
@@ -1188,6 +1686,53 @@ Sinatra приложения могут быть запущены напряму
|
|
1188
1686
|
-s # настроить rack сервер/обработчик (по умолчанию thin)
|
1189
1687
|
-x # включить мьютекс (по умолчанию выключен)
|
1190
1688
|
|
1689
|
+
== Системные требования
|
1690
|
+
|
1691
|
+
Следующие версии Ruby официально поддерживаются:
|
1692
|
+
|
1693
|
+
[ Ruby 1.8.7 ]
|
1694
|
+
1.8.7 полностью поддерживается, тем не менее, если вас ничто не держит на
|
1695
|
+
этой версии, рекомендуем обновиться до 1.9.2 или перейти на JRuby или Rubinius.
|
1696
|
+
|
1697
|
+
[ Ruby 1.9.2 ]
|
1698
|
+
1.9.2 поддерживается и рекомендована. Заметьте, что Radius и Markaby
|
1699
|
+
пока несовместимы с 1.9.2. Не используйте 1.9.2p0, известно, что эта
|
1700
|
+
версия весьма не стабильна при использовании Sinatra.
|
1701
|
+
|
1702
|
+
[ Rubinius ]
|
1703
|
+
Rubinius официально поддерживается (Rubinius >= 1.2.3), все, включая все
|
1704
|
+
языки шаблонов, работает.
|
1705
|
+
|
1706
|
+
[ JRuby ]
|
1707
|
+
JRuby официально поддерживается (JRuby >= 1.6.0). Нет никаких проблем с
|
1708
|
+
использованием альтернативных шаблонов. Тем не менее, если вы выбираете
|
1709
|
+
JRuby, то, пожалуйста, посмотрите на JRuby Rack-сервера, так как Thin не
|
1710
|
+
поддерживается полностью на JRuby. Поддержка расширений на C в JRuby все
|
1711
|
+
еще экспериментальная, что на данный момент затрагивает только RDiscount.
|
1712
|
+
|
1713
|
+
<b>Ruby 1.8.6 больше не поддерживается.</b>
|
1714
|
+
|
1715
|
+
Мы также следим за новыми версиями Ruby.
|
1716
|
+
|
1717
|
+
Следующие реализации Ruby не поддерживаются официально, но известно, что на
|
1718
|
+
них запускается Sinatra:
|
1719
|
+
|
1720
|
+
* Старые версии JRuby и Rubinius
|
1721
|
+
* MacRuby, Maglev, IronRuby
|
1722
|
+
* Ruby 1.9.0 и 1.9.1
|
1723
|
+
* Ruby 1.8.6 с помощью {backports}[https://github.com/marcandre/backports/#readme]
|
1724
|
+
|
1725
|
+
То, что версия официально не поддерживается, означает, что, если что-то не
|
1726
|
+
работает на этой версии, а на поддерживаемой работает, то мы предполагаем,
|
1727
|
+
что это не наша проблема, а их.
|
1728
|
+
|
1729
|
+
Мы также запускаем наши CI-тесты на последней версии Ruby (предстоящий 1.9.3),
|
1730
|
+
но мы не можем ничего гарантировать, так как она постоянно развивается.
|
1731
|
+
Предполагается, что 1.9.3p0 будет поддерживаться.
|
1732
|
+
|
1733
|
+
Sinatra должен работать на любой операционной системе, поддерживаемой выбранной
|
1734
|
+
реализацией Ruby.
|
1735
|
+
|
1191
1736
|
== На острие
|
1192
1737
|
|
1193
1738
|
Если вы хотите использовать самый последний код Sinatra, не бойтесь запускать
|
@@ -1228,7 +1773,7 @@ Sinatra приложения могут быть запущены напряму
|
|
1228
1773
|
=== Вручную
|
1229
1774
|
|
1230
1775
|
Создайте локальный клон репозитория и запускайте свое приложение с <tt>sinatra/lib</tt>
|
1231
|
-
директорией в <tt
|
1776
|
+
директорией в <tt>$LOAD_PATH</tt>:
|
1232
1777
|
|
1233
1778
|
cd myapp
|
1234
1779
|
git clone git://github.com/sinatra/sinatra.git
|
@@ -1252,6 +1797,11 @@ Sinatra приложения могут быть запущены напряму
|
|
1252
1797
|
|
1253
1798
|
sudo rake install
|
1254
1799
|
|
1800
|
+
== Версии
|
1801
|
+
|
1802
|
+
Sinatra использует {Semantic Versioning}[http://semver.org/], SemVer и
|
1803
|
+
SemVerTag.
|
1804
|
+
|
1255
1805
|
== Дальнейшее чтение
|
1256
1806
|
|
1257
1807
|
* {Вебсайт проекта}[http://www.sinatrarb.com/] - Дополнительная документация,
|