2010-10-26 17:57:10 -04:00
= Sinatra
<i>Внимание: Этот документ является переводом Английской версии и может быть устаревшим</i>
2010-10-29 09:55:07 -04:00
Sinatra — это предметно-ориентированный язык (DSL) для быстрого создания приложений на Ruby с
2010-10-26 17:57:10 -04:00
приложением минимума усилий:
# myapp.rb
require 'sinatra'
get '/' do
'Hello world!'
end
2010-10-29 09:55:07 -04:00
Установите gem и запустите приложение с помощью:
2010-10-26 17:57:10 -04:00
gem install sinatra
ruby -rubygems myapp.rb
Результат будет тут: http://localhost:4567
2010-10-29 09:55:07 -04:00
== Маршруты
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
В Sinatra маршрут — это пара: HTTP метод и шаблон (образец) URL.
Каждый маршрут ассоциирован с блоком:
2010-10-26 17:57:10 -04:00
get '/' do
.. что-то показать ..
end
post '/' do
.. что-то создать ..
end
put '/' do
.. что-то обновить ..
end
delete '/' do
.. что-то удалить ..
end
2010-10-29 09:55:07 -04:00
Маршруты сверяются с запросом по очередности определения. Первый же совпавший с запросом маршрут и будет вызван.
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
Шаблоны маршрутов могут включать в себя параметры доступные в
2010-10-26 17:57:10 -04:00
<tt>params</tt> xэше :
get '/hello/:name' do
2010-10-29 09:55:07 -04:00
# соответствует "GET /hello/foo" и "GET /hello/bar",
2010-10-26 17:57:10 -04:00
# где params[:name] 'foo' или 'bar'
"Hello #{params[:name]}!"
end
2010-10-29 09:55:07 -04:00
Можно также использовать именные параметры в переменных блоков:
2010-10-26 17:57:10 -04:00
get '/hello/:name' do |n|
"Hello #{n}!"
end
2010-10-29 09:55:07 -04:00
Шаблоны маршрутов также могут включать splat (wildcard, *, любая строка символов) параметры доступные
2010-10-26 17:57:10 -04:00
в <tt>params[:splat]</tt> массиве.
get '/say/*/to/*' do
2010-10-29 09:55:07 -04:00
# соответствует /say/hello/to/world
2010-10-26 17:57:10 -04:00
params[:splat] # => ["hello", "world"]
end
get '/download/*.*' do
2010-10-29 09:55:07 -04:00
# соответствует /download/path/to/file.xml
2010-10-26 17:57:10 -04:00
params[:splat] # => ["path/to/file", "xml"]
end
2010-10-29 09:55:07 -04:00
Маршруты также могут использовать регулярные выражение в качестве шаблона URL:
2010-10-26 17:57:10 -04:00
get %r{/hello/([\w]+)} do
"Hello, #{params[:captures].first}!"
end
2010-10-29 09:55:07 -04:00
Или с параметром блока:
2010-10-26 17:57:10 -04:00
get %r{/hello/([\w]+)} do |c|
"Hello, #{c}!"
end
=== Условия
2010-10-29 09:55:07 -04:00
Маршруты могут включать различные условия совпадений, такие как user agent:
2010-10-26 17:57:10 -04:00
get '/foo', :agent => /Songbird (\d\.\d)[\d\/]*?/ do
"You're using Songbird version #{params[:agent][0]}"
end
get '/foo' do
2010-10-29 09:55:07 -04:00
# соответствует с non-songbird браузерам
2010-10-26 17:57:10 -04:00
end
Другими доступными условиями являются +host_name+ и +provides+:
get '/', :host_name => /^admin\./ do
"Admin Area, Access denied!"
end
get '/', :provides => 'html' do
haml :index
end
get '/', :provides => ['rss', 'atom', 'xml'] do
builder :feed
end
2010-10-29 09:55:07 -04:00
Довольно легко можно задать собственные условия:
2010-10-26 17:57:10 -04:00
set(:probability) { |value| condition { rand <= value } }
get '/win_a_car', :probability => 0.1 do
"You won!"
end
get '/win_a_car' do
2010-10-29 09:55:07 -04:00
"Sorry, you lost."
2010-10-26 17:57:10 -04:00
end
=== Возвращаемые значения
2010-10-29 09:55:07 -04:00
Возвращаемое значение блока маршрута ограничивается телом ответа, которое будет передано HTTP клиенту,
или следующей подпрограммой (middleware) в Rack стеке. Чаще всего это строка, как в выше изложенных примерах.
Н о и другие значения также приемлимы.
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
Вы можете вернуть любой объект, который будет либо корректным Rack ответом, Rack
телом ответа, либо кодом состояния HTTP:
2010-10-26 17:57:10 -04:00
* Массив с тремя переменными: <tt>[status (Fixnum), headers (Hash), response body (должен отвечать на #each)]</tt>
* Массив с двумя переменными: <tt>[status (Fixnum), response body (должен отвечать на #each)]</tt>
2010-10-29 09:55:07 -04:00
* Объект, отвечающий на <tt>#each</tt>, который передает только строковые типы данных в этот блок
* Fixnum, соответствующий коду состояния HTTP
2010-10-26 17:57:10 -04:00
Таким образом мы легко можем создать поточный пример:
class Stream
def each
100.times { |i| yield "#{i}\n" }
end
end
get('/') { Stream.new }
2010-10-28 10:46:08 -04:00
== Статические файлы
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
Статические файлы отдаются из <tt>./public</tt> директории. Вы можете указать другое место,
используя <tt>:public</tt> опцию:
2010-10-26 17:57:10 -04:00
set :public, File.dirname(__FILE__) + '/static'
2010-10-29 09:55:07 -04:00
Учтите, что имя директории с о статическими файлами не включено в URL. Например, файл
2010-10-26 17:57:10 -04:00
<tt>./public/css/style.css</tt> будет доступен как
<tt>http://example.com/css/style.css</tt>.
== Виды / Шаблоны
2010-10-29 09:55:07 -04:00
Шаблоны по умолчанию будут использованы из директории <tt>./views</tt>.
2010-10-26 17:57:10 -04:00
Для использования другой директории:
set :views, File.dirname(__FILE__) + '/templates'
2010-10-29 09:55:07 -04:00
Важно помнить, что вы всегда должны указывать шаблоны
с помощью символов, даже если это подкаталог (в этом случае
2010-10-26 17:57:10 -04:00
успользуйте <tt>:'subdir/template'</tt>). Вы должны использовать
2010-10-29 09:55:07 -04:00
символ, иначе методы, ответственные за рендеринг, отобразят просто переданную им строку.
2010-10-26 17:57:10 -04:00
=== Haml шаблоны
2010-10-29 09:55:07 -04:00
Haml gem/библиотека необходима для рендеринга HAML шаблонов:
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
## Вам нужно будет подключить haml gem в приложении
2010-10-26 17:57:10 -04:00
require 'haml'
get '/' do
haml :index
end
2010-10-29 09:55:07 -04:00
Отрисует <tt>./views/index.haml</tt>.
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
{Опции Haml}[http://haml-lang.com/docs/yardoc/file.HAML_REFERENCE.html#options]
могут быть установлены глобально через конфигурацию Sinatra,
посмотрите {Опции и Конфигурация}[http://www.sinatrarb.com/configuration.html],
и переопределены локально.
2010-10-26 17:57:10 -04:00
set :haml, :format => :html5 # :xhtml - Haml формат по умолчанию
get '/' do
2010-10-29 09:55:07 -04:00
haml :index, :format => :html4 # переопределен
2010-10-26 17:57:10 -04:00
end
=== Erb шаблоны
2010-10-29 09:55:07 -04:00
## Вам нужно будет подключить erb в приложении
2010-10-26 17:57:10 -04:00
require 'erb'
get '/' do
erb :index
end
2010-10-29 09:55:07 -04:00
Отрисует <tt>./views/index.erb</tt>
2010-10-26 17:57:10 -04:00
=== Erubis шаблоны
2010-10-29 09:55:07 -04:00
Erubis gem/библиотека необходима для рендеринга erubis шаблонов:
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
## Вам нужно будет подключить erubis в приложении
2010-10-26 17:57:10 -04:00
require 'erubis'
get '/' do
erubis :index
end
2010-10-29 09:55:07 -04:00
Отрисует <tt>./views/index.erubis</tt>
2010-10-26 17:57:10 -04:00
=== Builder шаблоны
2010-10-29 09:55:07 -04:00
Builder gem/библиотека необходима для рендеринга builder шаблонов:
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
## Вам нужно будет подключить builder в приложении
2010-10-26 17:57:10 -04:00
require 'builder'
get '/' do
builder :index
end
2010-10-29 09:55:07 -04:00
Отрисует <tt>./views/index.builder</tt>.
2010-10-26 17:57:10 -04:00
=== Nokogiri шаблоны
2010-10-29 09:55:07 -04:00
Nokogiri gem/библиотека необходима для рендеринга nokogiri шаблонов:
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
## Вам нужно будет подключить nokogiri в приложении
2010-10-26 17:57:10 -04:00
require 'nokogiri'
get '/' do
nokogiri :index
end
2010-10-29 09:55:07 -04:00
Отрисует <tt>./views/index.nokogiri</tt>.
2010-10-26 17:57:10 -04:00
=== Sass шаблоны
2010-10-29 09:55:07 -04:00
Haml gem/библиотека необходима для рендеринга Sass шаблонов:
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
## Вам нужно будет подключить haml или sass в приложении
2010-10-26 17:57:10 -04:00
require 'sass'
get '/stylesheet.css' do
sass :stylesheet
end
2010-10-29 09:55:07 -04:00
Отрисует <tt>./views/stylesheet.sass</tt>.
2010-10-26 17:57:10 -04:00
{Опции Sass}[http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#options]
2010-10-29 09:55:07 -04:00
могут быть установлены глобально через конфигурацию Sinatra,
посмотрите {Опции и Конфигурация}[http://www.sinatrarb.com/configuration.html],
и переопределены локально.
2010-10-26 17:57:10 -04:00
set :sass, :style => :compact # :nested - стиль Sass по умолчанию
get '/stylesheet.css' do
2010-10-29 09:55:07 -04:00
sass :stylesheet, :style => :expanded # переопределен
2010-10-26 17:57:10 -04:00
end
=== Scss шаблоны
2010-10-29 09:55:07 -04:00
Haml gem/библиотека необходима для рендеринга Scss шаблонов:
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
## Вам нужно будет подключить haml или sass в приложении
2010-10-26 17:57:10 -04:00
require 'sass'
get '/stylesheet.css' do
scss :stylesheet
end
2010-10-29 09:55:07 -04:00
Отрисует <tt>./views/stylesheet.scss</tt>.
2010-10-26 17:57:10 -04:00
{Опции Scss}[http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#options]
2010-10-29 09:55:07 -04:00
могут быть установлены глобально через конфигурацию Sinatra,
посмотрите {Опции и Конфигурация}[http://www.sinatrarb.com/configuration.html],
и переопределены локально.
2010-10-26 17:57:10 -04:00
set :scss, :style => :compact # :nested - стиль Scss по умолчанию
get '/stylesheet.css' do
2010-10-29 09:55:07 -04:00
scss :stylesheet, :style => :expanded # переопределен
2010-10-26 17:57:10 -04:00
end
=== Less шаблоны
2010-10-29 09:55:07 -04:00
less gem/библиотека необходима для рендеринга Less шаблонов:
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
## Вам нужно будет подключить less в приложении
2010-10-26 17:57:10 -04:00
require 'less'
get '/stylesheet.css' do
less :stylesheet
end
2010-10-29 09:55:07 -04:00
Отрисует <tt>./views/stylesheet.less</tt>.
2010-10-26 17:57:10 -04:00
=== Liquid шаблоны
2010-10-29 09:55:07 -04:00
liquid gem/библиотека необходима для рендеринга liquid шаблонов:
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
## Вам нужно будет подключить liquid в приложении
2010-10-26 17:57:10 -04:00
require 'liquid'
get '/' do
liquid :index
end
2010-10-29 09:55:07 -04:00
Отрисует <tt>./views/index.liquid</tt>.
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
Так как в Liquid шаблонах невозможно вызывать методы из Ruby (кроме +yield+),
2010-10-26 17:57:10 -04:00
то вы почти всегда будете передавать локальные переменные:
liquid :index, :locals => { :key => 'value' }
=== Markdown шаблоны
2010-10-29 09:55:07 -04:00
rdiscount gem/библиотека необходима для рендеринга Markdown шаблонов:
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
## Вам нужно будет подключить rdiscount в приложении
2010-10-26 17:57:10 -04:00
require "rdiscount"
get '/' do
markdown :index
end
2010-10-29 09:55:07 -04:00
Отрисует <tt>./views/index.markdown</tt> (+md+ и +mkd+ также являются допустимыми файловыми
2010-10-26 17:57:10 -04:00
расширениями).
В markdown невозможно вызывать методы или передавать локальные переменные. Следовательно вам скорее всего прийдется
2010-10-29 09:55:07 -04:00
использовать этот шаблон совместно с другим движком рендеринга:
2010-10-26 17:57:10 -04:00
erb :overview, :locals => { :text => markdown(:introduction) }
2010-10-29 09:55:07 -04:00
Заметьте, что вы можете вызывать метод markdown из других шаблонов:
2010-10-26 17:57:10 -04:00
%h1 Hello From Haml!
%p= markdown(:greetings)
=== Textile шаблоны
2010-10-29 09:55:07 -04:00
RedCloth gem/библиотека необходима для рендеринга Textile шаблонов:
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
## Вам нужно будет подключить redcloth в приложении
2010-10-26 17:57:10 -04:00
require "redcloth"
get '/' do
textile :index
end
2010-10-29 09:55:07 -04:00
Отрисует <tt>./views/index.textile</tt>.
2010-10-26 17:57:10 -04:00
В textile невозможно вызывать методы или передавать локальные переменные. Следовательно вам скорее всего прийдется
2010-10-29 09:55:07 -04:00
использовать этот шаблон совместно с другим движком рендеринга:
2010-10-26 17:57:10 -04:00
erb :overview, :locals => { :text => textile(:introduction) }
2010-10-29 09:55:07 -04:00
Заметьте, что вы можете вызывать метод textile из других шаблонов:
2010-10-26 17:57:10 -04:00
%h1 Hello From Haml!
%p= textile(:greetings)
=== RDoc шаблоны
2010-10-29 09:55:07 -04:00
RDoc gem/библиотека необходима для рендеринга RDoc шаблонов:
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
## Вам нужно будет подключить rdoc в приложении
2010-10-26 17:57:10 -04:00
require "rdoc"
get '/' do
rdoc :index
end
2010-10-29 09:55:07 -04:00
Отрисует <tt>./views/index.rdoc</tt>.
2010-10-26 17:57:10 -04:00
В rdoc невозможно вызывать методы или передавать локальные переменные. Следовательно вам скорее всего прийдется
2010-10-29 09:55:07 -04:00
использовать этот шаблон совместно с другим движком рендеринга:
2010-10-26 17:57:10 -04:00
erb :overview, :locals => { :text => rdoc(:introduction) }
2010-10-29 09:55:07 -04:00
Заметьте, что вы можете вызывать метод rdoc из других шаблонов:
2010-10-26 17:57:10 -04:00
%h1 Hello From Haml!
%p= rdoc(:greetings)
=== Radius шаблоны
2010-10-29 09:55:07 -04:00
radius gem/библиотека необходима для рендеринга Radius шаблонов:
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
## Вам нужно будет подключить radius в приложении
2010-10-26 17:57:10 -04:00
require 'radius'
get '/' do
radius :index
end
2010-10-29 09:55:07 -04:00
Отрисует <tt>./views/index.radius</tt>.
2010-10-26 17:57:10 -04:00
Так как в Radius шаблоне невозможно вызывать методы из Ruby (кроме +yield+),
то вы почти всегда будете передавать локальные переменные:
radius :index, :locals => { :key => 'value' }
=== Markaby шаблоны
2010-10-29 09:55:07 -04:00
markaby gem/библиотека необходима для рендеринга Markaby шаблонов:
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
## Вам нужно будет подключить markaby в приложении
2010-10-26 17:57:10 -04:00
require 'markaby'
get '/' do
markaby :index
end
2010-10-29 09:55:07 -04:00
Отрисует <tt>./views/index.mab</tt>.
2010-10-26 17:57:10 -04:00
=== CoffeeScript шаблоны
2010-10-29 09:55:07 -04:00
coffee-script gem/библиотека и `coffee` бинарный файл необходимы для рендеринга CoffeeScript шаблонов:
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
## Вам нужно будет подключить coffee-script в приложении
2010-10-26 17:57:10 -04:00
require 'coffee-script'
get '/application.js' do
coffee :application
end
2010-10-29 09:55:07 -04:00
Отрисует <tt>./views/application.coffee</tt>.
2010-10-26 17:57:10 -04:00
=== Внутристроковые шаблоны
get '/' do
haml '%div.title Hello World'
end
2010-10-29 09:55:07 -04:00
Отрисует внутристроковый шаблон.
2010-10-26 17:57:10 -04:00
=== Доступ к переменным в шаблонах
2010-10-29 09:55:07 -04:00
Шаблоны интерпретируются в том же контексте, что и обработчики маршрутов. Переменные экзмепляра,
установленные в процесе обработки маршрутов, будут доступны напрямую в шаблонах:
2010-10-26 17:57:10 -04:00
get '/:id' do
@foo = Foo.find(params[:id])
haml '%h1= @foo.name'
end
2010-10-29 09:55:07 -04:00
Либо установите их через хеш локальных переменных:
2010-10-26 17:57:10 -04:00
get '/:id' do
foo = Foo.find(params[:id])
haml '%h1= foo.name', :locals => { :foo => foo }
end
2010-10-29 09:55:07 -04:00
Это обычно используется когда шаблоны рендерятся как частные (partials) из других шаблонов.
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
=== Вложенные шаблоны
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
Шаблоны также могут быть определены в конце файла-исходника:
2010-10-26 17:57:10 -04:00
require 'sinatra'
get '/' do
haml :index
end
__END__
@@ layout
%html
= yield
@@ index
%div.title Hello world!!!!!
2010-10-29 09:55:07 -04:00
Заметьте: Вложенные шаблоны, определенные в файле-исходнике, который подключил sinatra, будут
автоматически загружены. Вызовите <tt>enable :inline_templates</tt> напрямую, если у вас вложенные
2010-10-26 17:57:10 -04:00
шаблоны в других файлах.
=== Именные шаблоны
2010-10-29 09:55:07 -04:00
Шаблоны также могут быть определены используя <tt>template</tt> метод:
2010-10-26 17:57:10 -04:00
template :layout do
"%html\n =yield\n"
end
template :index do
'%div.title Hello World!'
end
get '/' do
haml :index
end
2010-10-29 09:55:07 -04:00
Если шаблон с именем "layout" существует, то он будет использован каждый раз,
когда шаблоны будут отрисовываться. Вы можете отключить layout-шаблон с помощью <tt>:layout => false</tt>.
2010-10-26 17:57:10 -04:00
get '/' do
haml :index, :layout => !request.xhr?
end
== Методы помощники
Используйте <tt>helpers</tt> метод для определения методов помощников для дальнейшего
2010-10-29 09:55:07 -04:00
использования в обработчиках маршрутов и шаблонах:
2010-10-26 17:57:10 -04:00
helpers do
def bar(name)
"#{name}bar"
end
end
get '/:name' do
bar(params[:name])
end
== Фильтры
2010-10-29 09:55:07 -04:00
Before-фильтры выполняются перед каждым запросом в том же контексте, что и маршруты. Фильтры могут изменять
как запрос, так и ответ на него. Переменные экземпляра, установленные в фильтрах, доступны в маршрутах и шаблонах:
2010-10-26 17:57:10 -04:00
before do
@note = 'Hi!'
request.path_info = '/foo/bar/baz'
end
get '/foo/*' do
@note #=> 'Hi!'
params[:splat] #=> 'bar/baz'
end
2010-10-29 09:55:07 -04:00
After-фильтры выполняются после каждого запроса в том же контексте, что и пути. Фильтры могут изменять
как запрос, так и ответ на него. Переменные экземпляра, установленные в before-фильтрах и маршрутах, будут доступны в after-фильтрах:
2010-10-26 17:57:10 -04:00
after do
puts response.status
end
2010-10-29 09:55:07 -04:00
Фильтры могут использовать шаблоны URL и будут интерпретированы только, если путь запроса совпадет с этим шаблоном:
2010-10-26 17:57:10 -04:00
before '/protected/*' do
authenticate!
end
after '/create/:slug' do |slug|
session[:last_slug] = slug
end
== Прерывание
2010-10-29 09:55:07 -04:00
Чтобы незамедлительно прервать обработку запроса внутри фильтра или маршрута используйте:
2010-10-26 17:57:10 -04:00
halt
Можно также указать статус при прерывании:
halt 410
2010-10-29 09:55:07 -04:00
Тело:
2010-10-26 17:57:10 -04:00
halt 'this will be the body'
2010-10-29 09:55:07 -04:00
И то, и другое:
2010-10-26 17:57:10 -04:00
halt 401, 'go away!'
Можно указать заголовки:
halt 402, {'Content-Type' => 'text/plain'}, 'revenge'
== Передача
2010-10-29 09:55:07 -04:00
Маршрут может передать обработку запроса следующему совпадающему маршруту, используя <tt>pass</tt>:
2010-10-26 17:57:10 -04:00
get '/guess/:who' do
pass unless params[:who] == 'Frank'
'You got me!'
end
get '/guess/*' do
'You missed!'
end
2010-10-29 09:55:07 -04:00
Блок маршрута сразу же прерывается, и контроль переходит к следующему совпадающему маршруту.
Если соответствующий маршрут не найден, то ответом на запрос будет 404.
2010-10-26 17:57:10 -04:00
== Доспут к объекту запроса
2010-10-29 09:55:07 -04:00
Объект входящего запроса доступен на уровне обработки запроса (в фильтрах, маршрутах, обработчиках ошибок)
с помощью `request` метода:
2010-10-26 17:57:10 -04:00
# приложение запущено на http://example.com/example
get '/foo' do
2010-10-29 09:55:07 -04:00
request.body # тело запроса, посланное клиентом (см. ниже)
2010-10-26 17:57:10 -04:00
request.scheme # "http"
request.script_name # "/example"
request.path_info # "/foo"
request.port # 80
request.request_method # "GET"
request.query_string # ""
request.content_length # длина тела запроса
request.media_type # медиа тип тела запроса
request.host # "example.com"
2010-10-29 09:55:07 -04:00
request.get? # true (для других участвующих HTTP глаголов есть похожие методы)
2010-10-26 17:57:10 -04:00
request.form_data? # false
request["SOME_HEADER"] # значение SOME_HEADER заголовка
request.referer # источник запроса клиента либо '/'
request.user_agent # user agent (используется для :agent условия)
request.cookies # хеш куки браузера
request.xhr? # является ли запрос ajax запросом?
request.url # "http://example.com/example/foo"
request.path # "/example/foo"
request.ip # IP адрес клиента
request.secure? # false
2010-10-29 09:55:07 -04:00
request.env # env хеш как получено Rack
2010-10-26 17:57:10 -04:00
end
Некоторые опции, такие как <tt>script_name</tt> или <tt>path_info</tt> могут быть переписаны:
before { request.path_info = "/" }
get "/" do
"all requests end up here"
end
2010-10-29 09:55:07 -04:00
<tt>request.body</tt> является IO или StringIO объектом:
2010-10-26 17:57:10 -04:00
post "/api" do
2010-10-29 09:55:07 -04:00
request.body.rewind # в случае, если кто-то уже прочитал тело запроса
2010-10-26 17:57:10 -04:00
data = JSON.parse request.body.read
"Hello #{data['name']}!"
end
== Конфигурация
2010-10-29 09:55:07 -04:00
Этот блок исполняется один раз при старте в любом окружении, режиме (environment):
2010-10-26 17:57:10 -04:00
configure do
...
end
2010-10-29 09:55:07 -04:00
Будет запущено, когда окружение (RACK_ENV переменная) установлена в
2010-10-26 17:57:10 -04:00
<tt>:production</tt>:
configure :production do
...
end
2010-10-29 09:55:07 -04:00
Будет запущено, когда окружение <tt>:production</tt> или <tt>:test</tt>:
2010-10-26 17:57:10 -04:00
configure :production, :test do
...
end
== Обработка ошибок
2010-10-29 09:55:07 -04:00
Обработчики ошибок исполняются в том же контексте, что и маршруты, before-фильтры, а это означает, что всякие
прелести вроде <tt>haml</tt>, <tt>erb</tt>, <tt>halt</tt> и т.д. доступны и им.
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
=== NotFound
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
Когда возбуждено исключение <tt>Sinatra::NotFound</tt>, или кодом ответа является 404,
то будет вызван <tt>not_found</tt> обработчик:
2010-10-26 17:57:10 -04:00
not_found do
'This is nowhere to be found.'
end
2010-10-29 09:55:07 -04:00
=== Ошибки
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
Обработчик ошибок +error+ будет вызван, когда исключение возбуждено из блока маршрута, либо из фильтра.
Объект-исключение доступен как переменная <tt>sinatra.error</tt> в Rack:
2010-10-26 17:57:10 -04:00
error do
'Sorry there was a nasty error - ' + env['sinatra.error'].name
end
Частные ошибки:
error MyCustomError do
'So what happened was...' + request.env['sinatra.error'].message
end
Тогда, если это произошло:
get '/' do
raise MyCustomError, 'something bad'
end
Т о вы получите:
So what happened was... something bad
2010-10-29 09:55:07 -04:00
Также вы можете установить обработчик ошибок для кода состояния HTTP:
2010-10-26 17:57:10 -04:00
error 403 do
'Access forbidden'
end
get '/secret' do
403
end
Либо набора кодов:
error 400..510 do
'Boom'
end
2010-10-29 09:55:07 -04:00
Sinatra устанавливает специальные <tt>not_found</tt> и <tt>error</tt> обработчики, когда запущена в режиме
разработки (окружение <tt>:development</tt>).
2010-10-26 17:57:10 -04:00
== Mime типы
2010-10-29 09:55:07 -04:00
Когда используете <tt>send_file</tt> или статические файлы, у вас могут быть mime типы которые Sinatra,
не понимает по умолчанию. Используйте +mime_type+ для их регистрации по расширению файла:
2010-10-26 17:57:10 -04:00
mime_type :foo, 'text/foo'
2010-10-29 09:55:07 -04:00
Вы также можете использовать это в +content_type+ помощнике:
2010-10-26 17:57:10 -04:00
content_type :foo
2010-10-29 09:55:07 -04:00
== Rack подпрограммы
2010-10-26 17:57:10 -04:00
Sinatra использует Rack[http://rack.rubyforge.org/], минимальный стандартный
2010-10-29 09:55:07 -04:00
интерфейс для веб-фреймворков на Ruby. Одной из самых интересных для разработчиков возможностей Rack
является поддержка подпрограмм ("middleware") -- компонентов,
"сидящих" между сервером и вашим приложением, которые отслеживают и/или манипулируют
HTTP запросами/ответами для предоставления различной функциональности.
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
В Sinatra очень просто использовать такие Rack подпрограммы с помощью метода +use+:
2010-10-26 17:57:10 -04:00
require 'sinatra'
require 'my_custom_middleware'
use Rack::Lint
use MyCustomMiddleware
get '/hello' do
'Hello World'
end
2010-10-29 09:55:07 -04:00
Семантика +use+ идентична той, что определена для
2010-10-26 17:57:10 -04:00
Rack::Builder[http://rack.rubyforge.org/doc/classes/Rack/Builder.html] DSL
(чаще всего используется в rackup файлах). Например, +use+ метод принимает
множественные переменные, также как и блоки:
use Rack::Auth::Basic do |username, password|
username == 'admin' && password == 'secret'
end
2010-10-29 09:55:07 -04:00
Rack распространяется с различными стандартными подпрограммами
для логирования, дебагинга, маршрутизации URL, аутентификации, обработки сессий. Sinatra использует
многие из этих компонентов автоматически, основываясь на конфигурации, чтобы вам не проходилось
регистрировать/использовать (+use+) их вручную.
2010-10-26 17:57:10 -04:00
== Тестирование
2010-10-29 09:55:07 -04:00
Тесты для Sinatra приложений могут быть написаны с помощью библиотек, фреймворков, поддерживающих
тестирование Rack. {Rack::Test}[http://gitrdoc.com/brynary/rack-test] рекомендован:
2010-10-26 17:57:10 -04:00
require 'my_sinatra_app'
require 'test/unit'
require 'rack/test'
class MyAppTest < Test::Unit::TestCase
include Rack::Test::Methods
def app
Sinatra::Application
end
def test_my_default
get '/'
assert_equal 'Hello World!', last_response.body
end
def test_with_params
get '/meet', :name => 'Frank'
assert_equal 'Hello Frank!', last_response.body
end
def test_with_rack_env
get '/', {}, 'HTTP_USER_AGENT' => 'Songbird'
assert_equal "You're using Songbird!", last_response.body
end
end
Заметьте: Встроенные модули Sinatra::Test и Sinatra::TestHarness являются
устаревшими начиная с 0.9.2 релиза.
2010-10-29 09:55:07 -04:00
== Sinatra::Base - Подпрограммы, библиотеки и модульные приложения
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
Описание своего приложения самым простейшим способом (с помощью DSL верхнего уровня, как в примерах выше)
работает отлично для крохотных приложений, но имеет множество недостатков, когда надо
создать компоненты такие как Rack
middleware, Rails metal, простые библиотеки с серверными компонентами,
Sinatra расширения.
DSL верхнего уровня загрязняет пространство имен <tt>Object</tt> и подразумевает стиль конфигурации
микро приложения (например, единый файл приложения, ./public и
2010-10-26 17:57:10 -04:00
./views директории, создание логов, страницу деталей о б исключениях
2010-10-29 09:55:07 -04:00
и т.д.). И тут на помощь приходит Sinatra::Base:
2010-10-26 17:57:10 -04:00
require 'sinatra/base'
class MyApp < Sinatra::Base
set :sessions, true
set :foo, 'bar'
get '/' do
'Hello world!'
end
end
2010-10-29 09:55:07 -04:00
MyApp класс является независимым Rack компонентом, который может исполнять роли
Rack подпрограммы, Rack приложения, Rails metal. Вы можете +use+ (использовать) или
+run+ (запустить) этот класс из rackup файла +config.ru+; или контролировать серверную
часть из библиотеки:
2010-10-26 17:57:10 -04:00
MyApp.run! :host => 'localhost', :port => 9090
2010-10-29 09:55:07 -04:00
Методы доступные Sinatra::Base сабклассам идентичны тем, что доступны
в DSL верхнего уровня. Большинство приложений верхнего уровня могут быть
2010-10-26 17:57:10 -04:00
конвертированы в Sinatra::Base компоненты с помощью двух модификаций:
2010-10-29 09:55:07 -04:00
* Вы должны подключать +sinatra/base+ вместо +sinatra+;
иначе, все методы предоставляемые Sinatra будут импортированные в глобальное пространство имен.
* Поместите все маршруты, обработчики ошибок, фильтры и опции в сабкласс Sinatra::Base.
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
<tt>Sinatra::Base</tt> — это чистый лист. Большинство опций, включая встроенный сервер, по умолчанию отключены.
Смотрите {Опции и Конфигурация}[http://www.sinatrarb.com/configuration.html] для детальной информации
о б опциях и их поведении.
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
=== Использование Sinatra как подпрограммы
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
Н е только сама Sinatra может использовать подпрограммы Rack, любое Sinatra приложение
само может быть добавлено к любому Rack эндпоинту в качестве подпрограммы. Этим эндпоинтом
может быть другое Sinatra приложение или приложение, основанное на Rack (Rails/Ramaze/Camping/...).
2010-10-26 17:57:10 -04:00
require 'sinatra/base'
class LoginScreen < Sinatra::Base
enable :session
get('/login') { haml :login }
post('/login') do
if params[:name] = 'admin' and params[:password] = 'admin'
session['user_name'] = params[:name]
else
redirect '/login'
end
end
end
class MyApp < Sinatra::Base
2010-10-29 09:55:07 -04:00
# подпрограмма будет запущена перед фильтрами
2010-10-26 17:57:10 -04:00
use LoginScreen
before do
unless session['user_name']
halt "Access denied, please <a href='/login'>login</a>."
end
end
get('/') { "Hello #{session['user_name']}." }
end
2010-10-29 09:55:07 -04:00
== Области видимости и привязка
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
Текущая область видимости определяет методы и переменные доступные
2010-10-26 17:57:10 -04:00
в данный момент.
=== Область видимости приложения / класса
Любое Sinatra приложение соответствует сабклассу Sinatra::Base. Если вы
2010-10-29 09:55:07 -04:00
используете DSL верхнего
2010-10-26 17:57:10 -04:00
уровня (<tt>require 'sinatra'</tt>), то этим классом будет
2010-10-29 09:55:07 -04:00
Sinatra::Application, иначе это будет сабкласс, который вы создали вручную.
Н а уровне класса вам будут доступны такие методы, как `get` или `before`, но вы
не сможете иметь доступ к объектам `request` или `session`, так как существует
только единый класс приложения для всех запросов.
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
Опции, созданные с помощью `set`, являются методами уровня класса:
2010-10-26 17:57:10 -04:00
class MyApp << Sinatra::Base
# Я в области видимости приложения!
set :foo, 42
foo # => 42
get '/foo' do
# Я больше не в области видимости приложения!
end
end
У вас будет область видимости приложения внутри:
2010-10-29 09:55:07 -04:00
* Тела вашего класса приложения
* Методов, определенных расширениями
* Блока, переданного в `helpers`
* Блоков, использованных как значения для `set`
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
Вы можете получить доступ к объекту области видимости (классу приложения) следующими способами:
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
* объект, переданный блокам конфигурации (<tt>configure { |c| ... }</tt>)
2010-10-26 17:57:10 -04:00
* `settings` внутри области видимости запроса
=== Область видимости запроса/экземпляра
2010-10-29 09:55:07 -04:00
Для каждого входящего запроса будет создан новый экземпляр вашего приложения,
и все блоки обработчика будут запущены в этом контексте. В этой области
видимости вам доступны `request` и `session` объекты, вызовы методов
рендеринга такие как `erb` или `haml`. Вы можете получить доступ к
области видимости приложения из контекста запроса используя помощник `settings`:
2010-10-26 17:57:10 -04:00
class MyApp << Sinatra::Base
# Я в области видимости приложения!
get '/define_route/:name' do
# Область видимости запроса '/define_route/:name'
@value = 42
settings.get("/#{params[:name]}") do
# Область видимости запроса "/#{params[:name]}"
@value # => nil (другой запрос)
end
"Route defined!"
end
end
У вас будет область видимости запроса внутри:
* get/head/post/put/delete блоков
* before/after фильтрах
* методах помощниках
* шаблонах/видах
2010-10-29 09:55:07 -04:00
=== Область видимости делегирования
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
Область видимости делегирования просто переправляет методы в область видимости класса.
2010-10-26 17:57:10 -04:00
Однако, оно не полностью на 100% ведет себя как область видимости класса,
2010-10-29 09:55:07 -04:00
так как у вас нету привязки к классу: только методы, явно помеченные для
делегирования, будут доступны, а переменных/состояний области видимости класса
не будет (иначе говоря: у вас будет другой `self` объект). Вы можете
непосредственно добавить методы делегирования, используя
2010-10-26 17:57:10 -04:00
<tt>Sinatra::Delegator.delegate :method_name</tt>.
У вас будет контекст делегирования внутри:
2010-10-29 09:55:07 -04:00
* Привязки верхнего уровня, если вы сделали <tt>require "sinatra"</tt>
* Объекта, расширенного с помощью примеси `Sinatra::Delegator`
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
Посмотрите сами в код: тут
2010-10-26 17:57:10 -04:00
{Sinatra::Delegator примесь}[http://github.com/sinatra/sinatra/blob/ceac46f0bc129a6e994a06100aa854f606fe5992/lib/sinatra/base.rb#L1128]
2010-10-29 09:55:07 -04:00
будет {включена в глобальное пространство имен}[http://github.com/sinatra/sinatra/blob/ceac46f0bc129a6e994a06100aa854f606fe5992/lib/sinatra/main.rb#L28].
2010-10-26 17:57:10 -04:00
== Командная строка
Sinatra приложения могут быть запущены напрямую:
ruby myapp.rb [-h] [-x] [-e ENVIRONMENT] [-p PORT] [-o HOST] [-s HANDLER]
Опции включают:
-h # помощь
-p # настроить порт (по умолчанию 4567)
-o # настроить хост (по умолчанию 0.0.0.0)
2010-10-29 09:55:07 -04:00
-e # настроить окружение, режим (по умолчанию development)
2010-10-26 17:57:10 -04:00
-s # настроить rack сервер/обработчик (по умолчанию thin)
2010-10-29 09:55:07 -04:00
-x # включить мьютекс (по умолчанию выключен)
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
== Н а острие
2010-10-26 17:57:10 -04:00
2010-10-29 09:55:07 -04:00
Если вы хотите использовать новейший код Sinatra, то создайте локальный
2010-10-26 17:57:10 -04:00
клон и запускайте свое приложение с <tt>sinatra/lib</tt> директорией
в <tt>LOAD_PATH</tt>:
cd myapp
git clone git://github.com/sinatra/sinatra.git
ruby -Isinatra/lib myapp.rb
2010-10-29 09:55:07 -04:00
Также вы можете добавить <tt>sinatra/lib</tt> директорию в
2010-10-26 17:57:10 -04:00
<tt>LOAD_PATH</tt> приложения:
$LOAD_PATH.unshift File.dirname(__FILE__) + '/sinatra/lib'
require 'rubygems'
require 'sinatra'
get '/about' do
"I'm running version " + Sinatra::VERSION
end
2010-10-29 09:55:07 -04:00
Чтобы обновить исходники Sinatra:
2010-10-26 17:57:10 -04:00
cd myproject/sinatra
git pull
== Больше информации
* {Вебсайт проекта}[http://www.sinatrarb.com/] - Дополнительная документация,
новости и ссылки на другие ресурсы.
2010-10-29 09:55:07 -04:00
* {Участие}[http://www.sinatrarb.com/contributing] - Нашли б а г ? Нужна помощь? Написали патч?
2010-10-26 17:57:10 -04:00
* {Слежение за проблемами}[http://github.com/sinatra/sinatra/issues]
* {Twitter}[http://twitter.com/sinatra]
* {Лист рассылки}[http://groups.google.com/group/sinatrarb/topics]
* {IRC: #sinatra}[irc://chat.freenode.net/#sinatra] on http://freenode.net