Внимание: Этот документ является переводом Английской версии и может быть устаревшим
Sinatra — это предметно-ориентированный язык (DSL) для быстрого создания приложений на Ruby с приложением минимума усилий:
# myapp.rb
require 'sinatra'
get '/' do
'Hello world!'
end
Установите gem и запустите приложение с помощью:
gem install sinatra
ruby -rubygems myapp.rb
Результат будет тут: localhost:4567
В Sinatra маршрут — это пара: HTTP метод и шаблон (образец) URL. Каждый маршрут ассоциирован с блоком:
get '/' do
.. что-то показать ..
end
post '/' do
.. что-то создать ..
end
put '/' do
.. что-то обновить ..
end
delete '/' do
.. что-то удалить ..
end
options '/' do
.. что-то ответить ..
end
Маршруты сверяются с запросом по очередности определения. Первый же совпавший с запросом маршрут и будет вызван.
Шаблоны маршрутов могут включать в себя параметры доступные в params
xэше:
get '/hello/:name' do
# соответствует "GET /hello/foo" и "GET /hello/bar",
# где params[:name] 'foo' или 'bar'
"Hello #{params[:name]}!"
end
Можно также использовать именные параметры в переменных блоков:
get '/hello/:name' do |n|
"Hello #{n}!"
end
Шаблоны маршрутов также могут включать splat (wildcard, *, любая строка символов) параметры доступные в params[:splat]
массиве.
get '/say/*/to/*' do
# соответствует /say/hello/to/world
params[:splat] # => ["hello", "world"]
end
get '/download/*.*' do
# соответствует /download/path/to/file.xml
params[:splat] # => ["path/to/file", "xml"]
end
Маршруты также могут использовать регулярные выражения в качестве шаблона URL:
get %r{/hello/([\w]+)} do
"Hello, #{params[:captures].first}!"
end
Или с параметром блока:
get %r{/hello/([\w]+)} do |c|
"Hello, #{c}!"
end
Маршруты могут включать различные условия совпадений, такие как user agent:
get '/foo', :agent => /Songbird (\d\.\d)[\d\/]*?/ do
"You're using Songbird version #{params[:agent][0]}"
end
get '/foo' do
# соответствует non-songbird браузерам
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
Довольно легко можно задать собственные условия:
set(:probability) { |value| condition { rand <= value } }
get '/win_a_car', :probability => 0.1 do
"You won!"
end
get '/win_a_car' do
"Sorry, you lost."
end
Возвращаемое значение блока маршрута ограничивается телом ответа, которое будет передано HTTP клиенту, или следующей “прослойкой” (middleware, промежуточная программа) в Rack стеке. Чаще всего это строка, как в вышеизложенных примерах. Но и другие значения также приемлемы.
Вы можете вернуть любой объект, который будет либо корректным Rack ответом, Rack телом ответа, либо кодом состояния HTTP:
-
Массив с тремя переменными:
[status (Fixnum), headers (Hash), response body (должен отвечать на #each)]
-
Массив с двумя переменными:
[status (Fixnum), response body (должен отвечать на #each)]
-
Объект, отвечающий на
#each
, который передает только строковые типы данных в этот блок -
Fixnum, соответствующий коду состояния HTTP
Таким образом мы легко можем создать поточный пример:
class Stream
def each
100.times { |i| yield "#{i}\n" }
end
end
get('/') { Stream.new }
Статические файлы отдаются из ./public
директории. Вы можете указать другое место, используя :public
опцию:
set :public, File.dirname(__FILE__) + '/static'
Учтите, что имя директории со статическими файлами не включено в URL. Например, файл ./public/css/style.css
будет доступен как http://example.com/css/style.css
.
Шаблоны по умолчанию будут использованы из директории ./views
. Для использования другой директории:
set :views, File.dirname(__FILE__) + '/templates'
Важно помнить, что вы всегда должны указывать шаблоны с помощью символов, даже если это подкаталог (в этом случае используйте :'subdir/template'
). Вы должны использовать символ, иначе методы, ответственные за рендеринг, отобразят просто переданную им строку.
haml
gem/библиотека необходима для рендеринга HAML шаблонов:
# Вам нужно будет подключить haml gem в приложении
require 'haml'
get '/' do
haml :index
end
Отрисует ./views/index.haml
.
Опции Haml могут быть установлены глобально через конфигурацию Sinatra, см. Опции и Конфигурация, и переопределены локально.
set :haml, :format => :html5 # :xhtml - Haml формат по умолчанию
get '/' do
haml :index, :format => :html4 # переопределен
end
# Вам нужно будет подключить erb в приложении
require 'erb'
get '/' do
erb :index
end
Отрисует ./views/index.erb
.
erubis
gem/библиотека необходима для рендеринга Erubis шаблонов:
# Вам нужно будет подключить Erubis в приложении
require 'erubis'
get '/' do
erubis :index
end
Отрисует ./views/index.erubis
.
Также возможно заменить Erb на Erubis:
require 'erubis'
Tilt.register :erb, Tilt[:erubis]
get '/' do
erb :index
end
Отрисует ./views/index.erb
с помощью Erubis.
builder
gem/библиотека необходима для рендеринга builder шаблонов:
# Вам нужно будет подключить builder в приложении
require 'builder'
get '/' do
builder :index
end
Отрисует ./views/index.builder
.
nokogiri
gem/библиотека необходима для рендеринга nokogiri шаблонов:
# Вам нужно будет подключить nokogiri в приложении
require 'nokogiri'
get '/' do
nokogiri :index
end
Отрисует ./views/index.nokogiri
.
haml
gem/библиотека необходима для рендеринга Sass шаблонов:
# Вам нужно будет подключить haml или sass в приложении
require 'sass'
get '/stylesheet.css' do
sass :stylesheet
end
Отрисует ./views/stylesheet.sass
.
Опции Sass могут быть установлены глобально через конфигурацию Sinatra, см. Опции и Конфигурация, и переопределены локально.
set :sass, :style => :compact # :nested - стиль Sass по умолчанию
get '/stylesheet.css' do
sass :stylesheet, :style => :expanded # переопределен
end
haml
gem/библиотека необходима для рендеринга Scss шаблонов:
# Вам нужно будет подключить haml или sass в приложении
require 'sass'
get '/stylesheet.css' do
scss :stylesheet
end
Отрисует ./views/stylesheet.scss
.
Опции Scss могут быть установлены глобально через конфигурацию Sinatra, см. Опции и Конфигурация, и переопределены локально.
set :scss, :style => :compact # :nested - стиль Scss по умолчанию
get '/stylesheet.css' do
scss :stylesheet, :style => :expanded # переопределен
end
less
gem/библиотека необходима для рендеринга Less шаблонов:
# Вам нужно будет подключить less в приложении
require 'less'
get '/stylesheet.css' do
less :stylesheet
end
Отрисует ./views/stylesheet.less
.
liquid
gem/библиотека необходима для рендеринга liquid шаблонов:
# Вам нужно будет подключить liquid в приложении
require 'liquid'
get '/' do
liquid :index
end
Отрисует ./views/index.liquid
.
Так как в Liquid шаблонах невозможно вызывать методы из Ruby (кроме yield
), то вы почти всегда будете передавать локальные переменные:
liquid :index, :locals => { :key => 'value' }
rdiscount
gem/библиотека необходима для рендеринга Markdown шаблонов:
# Вам нужно будет подключить rdiscount в приложении
require "rdiscount"
get '/' do
markdown :index
end
Отрисует ./views/index.markdown
(md
и mkd
также являются допустимыми файловыми расширениями).
В Markdown невозможно вызывать методы или передавать локальные переменные. Следовательно, вам, скорее всего, придется использовать этот шаблон совместно с другим движком рендеринга:
erb :overview, :locals => { :text => markdown(:introduction) }
Заметьте, что вы можете вызывать метод markdown
из других шаблонов:
%h1 Hello From Haml!
%p= markdown(:greetings)
Вы не можете вызывать Ruby из Markdown, соответственно, вы не можете использовать лэйаут-шаблоны (layouts) на Markdown. Тем не менее, есть возможность использовать один движок рендеринга для шаблона, а другой для лэйаута с помощью опции ‘:layout_engine`:
get '/' do
markdown :index, :layout_engine => :erb
end
Отрисует ./views/index.md
с ./views/layout.erb
в качестве лэйаута.
Также вы можете задать такие опции рендеринга глобально:
set :markdown, :layout_engine => :haml, :layout => :post
get '/' do
markdown :index
end
Отрисует ./views/index.md
(и любой другой шаблон на Markdown) с ./views/post.haml
в качестве лэйаута.
Также возможно обрабатывать Markdown с помощью BlueCloth, а не RDiscount:
require 'bluecloth'
Tilt.register 'markdown', BlueClothTemplate
Tilt.register 'mkd', BlueClothTemplate
Tilt.register 'md', BlueClothTemplate
get '/' do
markdown :index
end
Отрисует ./views/index.md
с помощью BlueCloth.
RedCloth
gem/библиотека необходима для рендеринга Textile шаблонов:
# Вам нужно будет подключить redcloth в приложении
require "redcloth"
get '/' do
textile :index
end
Отрисует ./views/index.textile
.
В Textile невозможно вызывать методы или передавать локальные переменные. Следовательно, вам, скорее всего, придется использовать этот шаблон совместно с другим движком рендеринга:
erb :overview, :locals => { :text => textile(:introduction) }
Заметьте, что вы можете вызывать метод textile
из других шаблонов:
%h1 Hello From Haml!
%p= textile(:greetings)
Вы не можете вызывать Ruby из Textile, соответственно, вы не можете использовать лэйаут-шаблоны на Textile. Тем не менее, есть возможность использовать один движок рендеринга для шаблона, а другой для лэйаута с помощью опции ‘:layout_engine`:
get '/' do
textile :index, :layout_engine => :erb
end
Отрисует ./views/index.textile
с ./views/layout.erb
в качестве лэйаута.
Также вы можете задать такие опции рендеринга глобально:
set :textile, :layout_engine => :haml, :layout => :post
get '/' do
textile :index
end
Отрисует ./views/index.textile
(и любой другой шаблон на Textile) с ./views/post.haml
в качестве лэйаута.
rdoc
gem/библиотека необходима для рендеринга RDoc шаблонов:
# Вам нужно будет подключить rdoc/markup/to_html в приложении
require "rdoc/markup/to_html"
get '/' do
rdoc :index
end
Отрисует ./views/index.rdoc
.
В RDoc невозможно вызывать методы или передавать локальные переменные. Следовательно, вам, скорее всего, придется использовать этот шаблон совместно с другим движком рендеринга:
erb :overview, :locals => { :text => rdoc(:introduction) }
Заметьте, что вы можете вызывать метод rdoc
из других шаблонов:
%h1 Hello From Haml!
%p= rdoc(:greetings)
Вы не можете вызывать Ruby из RDoc, соответственно, вы не можете использовать лэйаут-шаблоны на RDoc. Тем не менее, есть возможность использовать один движок рендеринга для шаблона, а другой для лэйаута с помощью опции ‘:layout_engine`:
get '/' do
rdoc :index, :layout_engine => :erb
end
Отрисует ./views/index.rdoc
с ./views/layout.erb
в качестве лэйаута.
Также вы можете задать такие опции рендеринга глобально:
set :rdoc, :layout_engine => :haml, :layout => :post
get '/' do
rdoc :index
end
Отрисует ./views/index.rdoc
(и любой другой шаблон на RDoc) с ./views/post.haml
в качестве лэйаута.
radius
gem/библиотека необходима для рендеринга Radius шаблонов:
# Вам нужно будет подключить radius в приложении
require 'radius'
get '/' do
radius :index
end
Отрисует ./views/index.radius
.
Так как в Radius шаблоне невозможно вызывать методы из Ruby (кроме yield
), то вы почти всегда будете передавать локальные переменные:
radius :index, :locals => { :key => 'value' }
markaby
gem/библиотека необходима для рендеринга Markaby шаблонов:
# Вам нужно будет подключить markaby в приложении
require 'markaby'
get '/' do
markaby :index
end
Отрисует ./views/index.mab
.
Вы также можете использовать внутристроковые Markaby шаблоны:
get '/' do
markaby { h1 "Welcome!" }
end
slim
gem/библиотека необходима для рендеринга slim шаблонов:
# Вам нужно будет подключить slim в приложении
require 'slim'
get '/' do
slim :index
end
Отрисует ./views/index.slim
.
Вам понадобится coffee-script
gem/библиотека и что-то одно из следующего списка, чтобы запускать JavaScript:
-
node
(из Node.js) -
вы можете использовать OSX (есть встроенные средства для выполнения JavaScript)
-
therubyracer
gem/библиотека
Подробнее смотрите на странице проекта.
Таким образом вы можете использовать CoffeeScript шаблоны.
# Вам нужно будет подключить coffee-script в приложении
require 'coffee-script'
get '/application.js' do
coffee :application
end
Отрисует ./views/application.coffee
.
get '/' do
haml '%div.title Hello World'
end
Отрисует встроенный (строчный) шаблон.
Шаблоны интерпретируются в том же контексте, что и обработчики маршрутов. Переменные экземпляра, установленные в процессе обработки маршрутов, будут доступны напрямую в шаблонах:
get '/:id' do
@foo = Foo.find(params[:id])
haml '%h1= @foo.name'
end
Либо установите их через хеш локальных переменных:
get '/:id' do
foo = Foo.find(params[:id])
haml '%h1= foo.name', :locals => { :foo => foo }
end
Это обычный подход, когда шаблоны рендерятся как частные (partials) из других шаблонов.
Шаблоны также могут быть определены в конце файла-исходника:
require 'sinatra'
get '/' do
haml :index
end
__END__
Заметьте: Вложенные шаблоны, определенные в файле-исходнике, который подключил Sinatra, будут автоматически загружены. Вызовите enable :inline_templates
напрямую, если у вас вложенные шаблоны в других файлах.
Шаблоны также могут быть определены, используя template
метод:
template :layout do
"%html\n =yield\n"
end
template :index do
'%div.title Hello World!'
end
get '/' do
haml :index
end
Если шаблон с именем “layout” существует, то он будет использован каждый раз, когда шаблоны будут отрисовываться. Вы можете отключать лэйаут в каждом конкретном случае с помощью :layout => false
или отключить его для всего приложения, например, так: set :haml, :layout => false
.
get '/' do
haml :index, :layout => !request.xhr?
end
Чтобы связать расширение файла и движок рендеринга, используйте Tilt.register
. Например, если вы хотите использовать расширение tt
для шаблонов Textile:
Tilt.register :tt, Tilt[:textile]
Сначала зарегистрируйте свой движок в Tilt, затем создайте метод, отвечающий за отрисовку:
Tilt.register :myat, MyAwesomeTemplateEngine
helpers do
def myat(*args) render(:myat, *args) end
end
get '/' do
myat :index
end
Отрисует ./views/index.myat
. Чтобы узнать больше о Tilt, смотрите github.com/rtomayko/tilt
Используйте метод helpers
, чтобы определить методы-помощники, которые в дальнейшем можно будет использовать в обработчиках маршрутов и шаблонах:
helpers do
def bar(name)
"#{name}bar"
end
end
get '/:name' do
bar(params[:name])
end
Before-фильтры выполняются перед каждым запросом в том же контексте, что и маршруты. Фильтры могут изменять как запрос, так и ответ на него. Переменные экземпляра, установленные в фильтрах, доступны в маршрутах и шаблонах:
before do
@note = 'Hi!'
request.path_info = '/foo/bar/baz'
end
get '/foo/*' do
@note #=> 'Hi!'
params[:splat] #=> 'bar/baz'
end
After-фильтры выполняются после каждого запроса в том же контексте, что и пути. Фильтры могут изменять как запрос, так и ответ на него. Переменные экземпляра, установленные в before-фильтрах и маршрутах, будут доступны в after-фильтрах:
after do
puts response.status
end
Фильтры могут использовать шаблоны URL и будут интерпретированы, только если путь запроса совпадет с этим шаблоном:
before '/protected/*' do
authenticate!
end
after '/create/:slug' do |slug|
session[:last_slug] = slug
end
Как и маршруты, фильтры могут использовать условия:
before :agent => /Songbird/ do
# ...
end
after '/blog/*', :host_name => 'example.com' do
# ...
end
Чтобы незамедлительно прервать обработку запроса внутри фильтра или маршрута, используйте:
halt
Можно также указать статус при прерывании:
halt 410
Тело:
halt 'this will be the body'
И то, и другое:
halt 401, 'go away!'
Можно указать заголовки:
halt 402, {'Content-Type' => 'text/plain'}, 'revenge'
Маршрут может передать обработку запроса следующему совпадающему маршруту, используя pass
:
get '/guess/:who' do
pass unless params[:who] == 'Frank'
'You got me!'
end
get '/guess/*' do
'You missed!'
end
Блок маршрута сразу же прерывается, и контроль переходит к следующему совпадающему маршруту. Если соответствующий маршрут не найден, то ответом на запрос будет 404.
Объект входящего запроса доступен на уровне обработки запроса (в фильтрах, маршрутах, обработчиках ошибок) с помощью ‘request` метода:
# приложение запущено на http://example.com/example
get '/foo' do
request.body # тело запроса, посланное клиентом (см. ниже)
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"
request.get? # true (есть аналоги для других методов HTTP)
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
request.env # "сырой" env хеш, полученный Rack
end
Некоторые опции, такие как script_name
или path_info
доступны для записи:
before { request.path_info = "/" }
get "/" do
"all requests end up here"
end
request.body
является IO или StringIO объектом:
post "/api" do
request.body.rewind # в случае, если кто-то уже прочитал тело запроса
data = JSON.parse request.body.read
"Hello #{data['name']}!"
end
Этот блок исполняется один раз при старте в любом окружении, режиме (environment):
configure do
...
end
Будет запущено, когда окружение (RACK_ENV переменная) установлена в :production
:
configure :production do
...
end
Будет запущено, когда окружение :production
или :test
:
configure :production, :test do
...
end
Обработчики ошибок исполняются в том же контексте, что и маршруты, before-фильтры, а это означает, что всякие прелести вроде haml
, erb
, halt
и т.д. доступны и им.
Когда возбуждено исключение Sinatra::NotFound
, или кодом ответа является 404, то будет вызван not_found
обработчик:
not_found do
'This is nowhere to be found.'
end
Обработчик ошибок error
будет вызван, когда исключение возбуждено из блока маршрута, либо из фильтра. Объект-исключение доступен как переменная sinatra.error
в Rack:
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
Также вы можете установить обработчик ошибок для кода состояния HTTP:
error 403 do
'Access forbidden'
end
get '/secret' do
403
end
Либо набора кодов:
error 400..510 do
'Boom'
end
Sinatra устанавливает специальные not_found
и error
обработчики, когда запущена в режиме разработки (окружение :development
).
Когда вы используете send_file
или статические файлы, у вас могут быть mime-типы, которые Sinatra не понимает по умолчанию. Используйте mime_type
для их регистрации по расширению файла:
mime_type :foo, 'text/foo'
Вы также можете использовать это в content_type
помощнике:
content_type :foo
Sinatra использует Rack, минимальный стандартный интерфейс для веб-фреймворков на Ruby. Одной из самых интересных для разработчиков возможностей Rack является поддержка “прослоек” (“middleware”) — компонентов, “сидящих” между сервером и вашим приложением, которые отслеживают и/или манипулируют HTTP запросами/ответами для предоставления различной функциональности.
В Sinatra очень просто использовать такие “прослойки” с помощью метода use
:
require 'sinatra'
require 'my_custom_middleware'
use Rack::Lint
use MyCustomMiddleware
get '/hello' do
'Hello World'
end
Семантика use
идентична той, что определена для Rack::Builder DSL (чаще всего используется в rackup файлах). Например, use
метод принимает множественные переменные, также как и блоки:
use Rack::Auth::Basic do |username, password|
username == 'admin' && password == 'secret'
end
Rack распространяется с различными стандартными “прослойками” для логирования, отладки, маршрутизации URL, аутентификации, обработки сессий. Sinatra использует многие из этих компонентов автоматически, основываясь на конфигурации, чтобы вам не приходилось регистрировать/использовать (use
) их вручную.
Тесты для Sinatra приложений могут быть написаны с помощью библиотек, фреймворков, поддерживающих тестирование Rack. Rack::Test рекомендован:
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.
Описание своего приложения самым простейшим способом (с помощью DSL верхнего уровня, как в примерах выше) работает отлично для крохотных приложений, но имеет множество недостатков, когда надо создать компоненты, такие как Rack middleware (“прослойки”), Rails metal, простые библиотеки с серверными компонентами, расширения Sinatra. DSL верхнего уровня загрязняет пространство имен Object
и подразумевает стиль конфигурации микро-приложения (например, единый файл приложения, ./public и ./views директории, создание логов, страницу деталей об исключениях и т.д.). И тут на помощь приходит Sinatra::Base:
require 'sinatra/base'
class MyApp < Sinatra::Base
set :sessions, true
set :foo, 'bar'
get '/' do
'Hello world!'
end
end
Методы, доступные Sinatra::Base сабклассам идентичны тем, что доступны в DSL верхнего уровня. Большинство приложений верхнего уровня могут быть конвертированы в Sinatra::Base компоненты с помощью двух модификаций:
-
Вы должны подключать
sinatra/base
вместоsinatra
, иначе все методы предоставляемые Sinatra будут импортированные в глобальное пространство имен. -
Поместите все маршруты, обработчики ошибок, фильтры и опции в сабкласс Sinatra::Base.
Sinatra::Base
— это чистый лист. Большинство опций, включая встроенный сервер, по умолчанию отключены. Смотрите Опции и Конфигурация для детальной информации об опциях и их поведении.
Есть два общепринятых способа запускать модульные приложения: запуск напрямую с помощью run!
:
# my_app.rb
require 'sinatra/base'
class MyApp < Sinatra::Base
# ... здесь код приложения ...
# запускаем сервер, если исполняется текущий файл
run! if app_file == $0
end
И запускаем с помощью:
ruby my_app.rb
Или с помощью конфигурационного файла config.ru
, который позволяет использовать любой Rack-совместимый сервер приложений.
# config.ru
require 'my_app'
run MyApp
Запускаем:
rackup -p 4567
Файл приложения:
# app.rb
require 'sinatra'
get '/' do
'Hello world!'
end
И соответствующий config.ru
:
require 'app'
run Sinatra::Application
Вот несколько причин, по которым вы, возможно, захотите использовать config.ru
:
-
вы хотите разворачивать свое приложение на различных Rack-совместимых серверах (Passenger, Unicorn, Heroku, …).
-
вы хотите использовать более одного сабкласса
Sinatra::Base
. -
вы хотите использовать Sinatra только в качестве “прослойки” Rack.
Совсем необязательно переходить на использование config.ru
лишь потому, что вы стали использовать модульный стиль приложения. И необязательно использовать модульный стиль, чтобы запускать приложение с помощью config.ru
.
Не только сама Sinatra может использовать “прослойки” Rack, но и любое Sinatra приложение само может быть добавлено к любому Rack эндпоинту в качестве “прослойки”. Этим эндпоинтом может быть другое Sinatra приложение, или приложение, основанное на Rack (Rails/Ramaze/Camping/…).
require 'sinatra/base'
class LoginScreen < Sinatra::Base
enable :sessions
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
# "прослойка" будет запущена перед фильтрами
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
Текущая область видимости определяет методы и переменные, доступные в данный момент.
Любое Sinatra приложение соответствует сабклассу Sinatra::Base. Если вы используете DSL верхнего уровня (require 'sinatra'
), то этим классом будет Sinatra::Application, иначе это будет сабкласс, который вы создали вручную. На уровне класса вам будут доступны такие методы, как ‘get` или `before`, но вы не сможете иметь доступ к объектам `request` или `session`, так как существует только единый класс приложения для всех запросов.
Опции, созданные с помощью ‘set`, являются методами уровня класса:
class MyApp < Sinatra::Base
# Я в области видимости приложения!
set :foo, 42
foo # => 42
get '/foo' do
# Я больше не в области видимости приложения!
end
end
У вас будет область видимости приложения внутри:
-
Тела вашего класса приложения
-
Методов, определенных расширениями
-
Блока, переданного в ‘helpers`
-
Блоков, использованных как значения для ‘set`
Вы можете получить доступ к объекту области видимости (классу приложения) следующими способами:
-
объект, переданный блокам конфигурации (
configure { |c| ... }
) -
‘settings` внутри области видимости запроса
Для каждого входящего запроса будет создан новый экземпляр вашего приложения, и все блоки обработчика будут запущены в этом контексте. В этой области видимости вам доступны ‘request` и `session` объекты, вызовы методов рендеринга, такие как `erb` или `haml`. Вы можете получить доступ к области видимости приложения из контекста запроса, используя помощник `settings`:
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/options блоков
-
before/after фильтрах
-
методах помощниках
-
шаблонах/видах
Область видимости делегирования просто перенаправляет методы в область видимости класса. Однако, оно не полностью на 100% ведет себя как область видимости класса, так как у вас нету привязки к классу: только методы, явно помеченные для делегирования, будут доступны, а переменных/состояний области видимости класса не будет (иначе говоря, у вас будет другой ‘self` объект). Вы можете непосредственно добавить методы делегирования, используя Sinatra::Delegator.delegate :method_name
.
У вас будет контекст делегирования внутри:
-
Привязки верхнего уровня, если вы сделали
require "sinatra"
-
Объекта, расширенного с помощью примеси ‘Sinatra::Delegator`
Посмотрите сами в код: тут Sinatra::Delegator примесь будет включена в глобальное пространство имен.
Sinatra приложения могут быть запущены напрямую:
ruby myapp.rb [-h] [-x] [-e ENVIRONMENT] [-p PORT] [-o HOST] [-s HANDLER]
Опции включают:
-h # помощь
-p # настроить порт (по умолчанию 4567)
-o # настроить хост (по умолчанию 0.0.0.0)
-e # настроить окружение, режим (по умолчанию development)
-s # настроить rack сервер/обработчик (по умолчанию thin)
-x # включить мьютекс (по умолчанию выключен)
Если вы хотите использовать самый последний код Sinatra, не бойтесь запускать свое приложение вместе с master бранчем Sinatra, он весьма стабилен.
Мы также время от времени выпускаем предварительные версии, так что вы можете делать так:
gem install sinatra --pre
Чтобы воспользоваться некоторыми самыми последними возможностям.
Если вы хотите запускать свое приложение с последней версией Sinatra, то рекомендуем использовать Bundler.
Сначала установите Bundler, если у вас его еще нет:
gem install bundler
Затем создайте файл Gemfile
в директории вашего проекта:
source :rubygems
gem 'sinatra', :git => "git://github.com/sinatra/sinatra.git"
# другие зависимости
gem 'haml' # например, если используете haml
gem 'activerecord', '~> 3.0' # может быть, вам нужен и ActiveRecord 3.x
Обратите внимание, вам нужно будет указывать все зависимости вашего приложения в этом файле. Однако, непосредственные зависимости Sinatra (Rack и Tilt) Bundler автоматически скачает и добавит.
Теперь вы можете запускать свое приложение примерно так:
bundle exec ruby myapp.rb
Создайте локальный клон репозитория и запускайте свое приложение с sinatra/lib
директорией в LOAD_PATH
:
cd myapp
git clone git://github.com/sinatra/sinatra.git
ruby -Isinatra/lib myapp.rb
Чтобы обновить исходники Sinatra:
cd myapp/sinatra
git pull
Вы можете самостоятельно собрать gem:
git clone git://github.com/sinatra/sinatra.git
cd sinatra
rake sinatra.gemspec
rake install
Если вы устанавливаете пакеты (gem) от пользователя root, то вашим последним шагом должна быть команда
sudo rake install
-
Вебсайт проекта - Дополнительная документация, новости и ссылки на другие ресурсы.
-
Участие - Нашли баг? Нужна помощь? Написали патч?
-
#sinatra on freenode.net