sinatra/README.jp.md

1097 lines
34 KiB
Markdown
Raw Normal View History

2013-03-04 16:25:59 +00:00
# Sinatra
2013-03-04 16:25:59 +00:00
*注)
本文書は英語から翻訳したものであり、その内容が最新でない場合もあります。最新の情報はオリジナルの英語版を参照して下さい。*
2013-03-04 16:25:59 +00:00
[DSL](http://ja.wikipedia.org/wiki/ドメイン固有言語)です。
# myapp.rb
require 'sinatra'
get '/' do
'Hello world!'
end
gemをインストールして動かしてみる。
2013-03-04 16:25:59 +00:00
gem install sinatra
ruby myapp.rb
2013-03-04 16:25:59 +00:00
[localhost:4567](http://localhost:4567) を見る。
2013-03-04 16:25:59 +00:00
## ルート
Sinatraでは、ルートはHTTPメソッドとURLマッチングパターンがペアになっています。
ルートはブロックに結び付けられています。
2013-03-04 16:25:59 +00:00
get '/' do
.. 何か見せる ..
end
2013-03-04 16:25:59 +00:00
post '/' do
.. 何か生成する ..
end
2013-03-04 16:25:59 +00:00
put '/' do
.. 何か更新する ..
end
2013-03-04 16:25:59 +00:00
delete '/' do
.. 何か削除する ..
end
2013-03-04 16:25:59 +00:00
ルートは定義された順番にマッチします。
リクエストに最初にマッチしたルートが呼び出されます。
ルートのパターンは名前付きパラメータを含むことができ、
2013-03-04 16:25:59 +00:00
`params`ハッシュで取得できます。
2013-03-04 16:25:59 +00:00
get '/hello/:name' do
# matches "GET /hello/foo" and "GET /hello/bar"
# params[:name] is 'foo' or 'bar'
"Hello #{params[:name]}!"
end
また、ブロックパラメータで名前付きパラメータにアクセスすることもできます。
2013-03-04 16:25:59 +00:00
get '/hello/:name' do |n|
"Hello #{n}!"
end
ルートパターンはsplat(またはワイルドカード)を含むこともでき、
2013-03-04 16:25:59 +00:00
`params[:splat]` で取得できます。
2013-03-04 16:25:59 +00:00
get '/say/*/to/*' do
# matches /say/hello/to/world
params[:splat] # => ["hello", "world"]
end
2013-03-04 16:25:59 +00:00
get '/download/*.*' do
# matches /download/path/to/file.xml
params[:splat] # => ["path/to/file", "xml"]
end
ブロックパラーメータを使用した場合:
2013-03-04 16:25:59 +00:00
get '/download/*.*' do |path, ext|
[path, ext] # => ["path/to/file", "xml"]
end
正規表現を使ったルート:
2013-03-04 16:25:59 +00:00
get %r{/hello/([\w]+)} do
"Hello, #{params[:captures].first}!"
end
ブロックパラーメータを使用した場合:
2013-03-04 16:25:59 +00:00
get %r{/hello/([\w]+)} do |c|
"Hello, #{c}!"
end
2013-03-04 16:25:59 +00:00
### 条件
ルートにはユーザエージェントのようなさまざまな条件を含めることができます。
2013-03-04 16:25:59 +00:00
get '/foo', :agent => /Songbird (\d\.\d)[\d\/]*?/ do
"You're using Songbird version #{params[:agent][0]}"
end
get '/foo' do
# Matches non-songbird browsers
end
2013-03-04 16:25:59 +00:00
ほかに`host_name`と`provides`条件が利用可能です:
2013-03-04 16:25:59 +00:00
get '/', :host_name => /^admin\./ do
"Admin Area, Access denied!"
end
2013-03-04 16:25:59 +00:00
get '/', :provides => 'html' do
haml :index
end
2013-03-04 16:25:59 +00:00
get '/', :provides => ['rss', 'atom', 'xml'] do
builder :feed
end
独自の条件を定義することも簡単にできます:
2013-03-04 16:25:59 +00:00
set(:probability) { |value| condition { rand <= value } }
get '/win_a_car', :probability => 0.1 do
"You won!"
end
2013-03-04 16:25:59 +00:00
get '/win_a_car' do
"Sorry, you lost."
end
2013-03-04 16:25:59 +00:00
### 戻り値
ルートブロックの戻り値は、HTTPクライアントまたはRackスタックでの次のミドルウェアに渡されるレスポンスボディを決定します。
これは大抵の場合、上の例のように文字列ですが、それ以外の値も使用することができます。
Rackレスポンス、Rackボディオブジェクト、HTTPステータスコードのいずれかとして
妥当なオブジェクトであればどのようなオブジェクトでも返すことができます:
2013-03-04 16:25:59 +00:00
- 3要素の配列:
`[ステータス(Fixnum), ヘッダ(Hash), レスポンスボディ(#eachに応答する)]`
- 2要素の配列:
`[ステータス(Fixnum), レスポンスボディ(#eachに応答する)]`
- `#each`に応答し、与えられたブロックに文字列を渡すオブジェクト
- ステータスコードを表現するFixnum
そのように、例えばストリーミングの例を簡単に実装することができます:
class Stream
def each
100.times { |i| yield "#{i}\n" }
end
end
get('/') { Stream.new }
2013-03-04 16:25:59 +00:00
## 静的ファイル
2013-03-04 16:25:59 +00:00
静的ファイルは`./public`ディレクトリから配信されます。
`:public_folder`オプションを指定することで別の場所を指定することができます。
2013-03-04 16:25:59 +00:00
set :public_folder, File.dirname(__FILE__) + '/static'
注意: この静的ファイル用のディレクトリ名はURL中に含まれません。
2013-03-04 16:25:59 +00:00
例えば、`./public/css/style.css`は`http://example.com/css/style.css`でアクセスできます。
2013-03-04 16:25:59 +00:00
## ビュー / テンプレート
2013-03-04 16:25:59 +00:00
テンプレートは`./views`ディレクトリ下に配置されています。
他のディレクトリを使用する場合の例:
2013-03-04 16:25:59 +00:00
set :views, File.dirname(__FILE__) + '/templates'
テンプレートはシンボルを使用して参照させることを覚えておいて下さい。
2013-03-04 16:25:59 +00:00
サブデレクトリでもこの場合は`:'subdir/template'`のようにします。
レンダリングメソッドは文字列が渡されると、そのまま文字列を出力します。
2013-03-04 16:25:59 +00:00
### Haml テンプレート
hamlを使うにはhamlライブラリが必要です:
2013-03-04 16:25:59 +00:00
# hamlを読み込みます
require 'haml'
2013-03-04 16:25:59 +00:00
get '/' do
haml :index
end
2013-03-04 16:25:59 +00:00
`./views/index.haml`を表示します。
2013-03-04 16:25:59 +00:00
[Hamls
options](http://haml.info/docs/yardoc/file.HAML_REFERENCE.html#options)
はSinatraの設定でグローバルに設定することができます。 [Options and
Configurations](http://www.sinatrarb.com/configuration.html),
を参照してそれぞれ設定を上書きして下さい。
2013-03-04 16:25:59 +00:00
set :haml, {:format => :html5 } # デフォルトのフォーマットは:xhtml
2013-03-04 16:25:59 +00:00
get '/' do
haml :index, :haml_options => {:format => :html4 } # 上書き
end
2013-03-04 16:25:59 +00:00
### Erb テンプレート
2013-03-04 16:25:59 +00:00
# erbを読み込みます
require 'erb'
2013-03-04 16:25:59 +00:00
get '/' do
erb :index
end
2013-03-04 16:25:59 +00:00
`./views/index.erb`を表示します。
2013-03-04 16:25:59 +00:00
### Erubis
erubisテンプレートを表示するには、erubisライブラリが必要です:
2013-03-04 16:25:59 +00:00
# erubisを読み込みます
require 'erubis'
2013-03-04 16:25:59 +00:00
get '/' do
erubis :index
end
2013-03-04 16:25:59 +00:00
`./views/index.erubis`を表示します。
2013-03-04 16:25:59 +00:00
### Builder テンプレート
builderを使うにはbuilderライブラリが必要です:
2013-03-04 16:25:59 +00:00
# builderを読み込みます
require 'builder'
2013-03-04 16:25:59 +00:00
get '/' do
builder :index
end
2013-03-04 16:25:59 +00:00
`./views/index.builder`を表示します。
2013-03-04 16:25:59 +00:00
### 鋸 テンプレート
鋸を使うには鋸ライブラリが必要です:
2013-03-04 16:25:59 +00:00
# 鋸を読み込みます
require 'nokogiri'
2013-03-04 16:25:59 +00:00
get '/' do
nokogiri :index
end
2013-03-04 16:25:59 +00:00
`./views/index.nokogiri`を表示します。
2013-03-04 16:25:59 +00:00
### Sass テンプレート
Sassテンプレートを使うにはsassライブラリが必要です:
2013-03-04 16:25:59 +00:00
# hamlかsassを読み込みます
require 'sass'
2013-03-04 16:25:59 +00:00
get '/stylesheet.css' do
sass :stylesheet
end
2013-03-04 16:25:59 +00:00
`./views/stylesheet.sass`を表示します。
2013-03-04 16:25:59 +00:00
[Sass
options](http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#options)
はSinatraの設定でグローバルに設定することができます。 see [Options and
Configurations](http://www.sinatrarb.com/configuration.html),
を参照してそれぞれ設定を上書きして下さい。
2013-03-04 16:25:59 +00:00
set :sass, {:style => :compact } # デフォルトのSass styleは :nested
2013-03-04 16:25:59 +00:00
get '/stylesheet.css' do
sass :stylesheet, :sass_options => {:style => :expanded } # 上書き
end
2013-03-04 16:25:59 +00:00
### Scss テンプレート
Scssテンプレートを使うにはsassライブラリが必要です:
2013-03-04 16:25:59 +00:00
# hamlかsassを読み込みます
require 'sass'
2013-03-04 16:25:59 +00:00
get '/stylesheet.css' do
scss :stylesheet
end
2013-03-04 16:25:59 +00:00
`./views/stylesheet.scss`を表示します。
2013-03-04 16:25:59 +00:00
[Sass
options](http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#options)
はSinatraの設定でグローバルに設定することができます。 see [Options and
Configurations](http://www.sinatrarb.com/configuration.html),
を参照してそれぞれ設定を上書きして下さい。
2013-03-04 16:25:59 +00:00
set :scss, :style => :compact # デフォルトのScss styleは:nested
2013-03-04 16:25:59 +00:00
get '/stylesheet.css' do
scss :stylesheet, :style => :expanded # 上書き
end
2013-03-04 16:25:59 +00:00
### Less テンプレート
Lessテンプレートを使うにはlessライブラリが必要です:
2013-03-04 16:25:59 +00:00
# lessを読み込みます
require 'less'
2013-03-04 16:25:59 +00:00
get '/stylesheet.css' do
less :stylesheet
end
2013-03-04 16:25:59 +00:00
`./views/stylesheet.less`を表示します。
2013-03-04 16:25:59 +00:00
### Liquid テンプレート
Liquidテンプレートを使うにはliquidライブラリが必要です:
2013-03-04 16:25:59 +00:00
# liquidを読み込みます
require 'liquid'
2013-03-04 16:25:59 +00:00
get '/' do
liquid :index
end
2013-03-04 16:25:59 +00:00
`./views/index.liquid`を表示します。
2013-03-04 16:25:59 +00:00
LiquidテンプレートからRubyのメソッド(`yield`を除く)を呼び出すことができないため、
ほぼ全ての場合にlocalsを指定する必要があるでしょう:
2013-03-04 16:25:59 +00:00
liquid :index, :locals => { :key => 'value' }
2013-03-04 16:25:59 +00:00
### Markdown テンプレート
Markdownテンプレートを使うにはrdiscountライブラリが必要です:
2013-03-04 16:25:59 +00:00
# rdiscountを読み込みます
require "rdiscount"
2013-03-04 16:25:59 +00:00
get '/' do
markdown :index
end
`./views/index.markdown`を表示します。(`md`と`mkd`も妥当な拡張子です)
markdownからメソッドを呼び出すことも、localsに変数を渡すこともできません。
それゆえ、他のレンダリングエンジンとの組み合わせで使うのが普通です:
2013-03-04 16:25:59 +00:00
erb :overview, :locals => { :text => markdown(:introduction) }
他のテンプレートからmarkdownメソッドを呼び出してもよいことに注意してください:
2013-03-04 16:25:59 +00:00
%h1 Hello From Haml!
%p= markdown(:greetings)
2013-03-04 16:25:59 +00:00
### Textile テンプレート
Textileテンプレートを使うにはRedClothライブラリが必要です:
2013-03-04 16:25:59 +00:00
# redclothを読み込みます
require "redcloth"
2013-03-04 16:25:59 +00:00
get '/' do
textile :index
end
2013-03-04 16:25:59 +00:00
`./views/index.textile`を表示します。
textileからメソッドを呼び出すことも、localsに変数を渡すこともできません。
それゆえ、他のレンダリングエンジンとの組み合わせで使うのが普通です:
2013-03-04 16:25:59 +00:00
erb :overview, :locals => { :text => textile(:introduction) }
他のテンプレートからtextileメソッドを呼び出してもよいことに注意してください:
2013-03-04 16:25:59 +00:00
%h1 Hello From Haml!
%p= textile(:greetings)
2013-03-04 16:25:59 +00:00
### RDoc テンプレート
RDocテンプレートを使うにはRDocライブラリが必要です:
2013-03-04 16:25:59 +00:00
# rdoc/markup/to_htmlを読み込みます
require "rdoc"
require "rdoc/markup/to_html"
2013-03-04 16:25:59 +00:00
get '/' do
rdoc :index
end
2013-03-04 16:25:59 +00:00
`./views/index.rdoc`を表示します。
rdocからメソッドを呼び出すことも、localsに変数を渡すこともできません。
それゆえ、他のレンダリングエンジンとの組み合わせで使うのが普通です:
2013-03-04 16:25:59 +00:00
erb :overview, :locals => { :text => rdoc(:introduction) }
他のテンプレートからrdocメソッドを呼び出してもよいことに注意してください:
2013-03-04 16:25:59 +00:00
%h1 Hello From Haml!
%p= rdoc(:greetings)
2013-03-04 16:25:59 +00:00
### Radius テンプレート
Radiusテンプレートを使うにはradiusライブラリが必要です:
2013-03-04 16:25:59 +00:00
# radiusを読み込みます
require 'radius'
2013-03-04 16:25:59 +00:00
get '/' do
radius :index
end
2013-03-04 16:25:59 +00:00
`./views/index.radius`を表示します。
2013-03-04 16:25:59 +00:00
RadiusテンプレートからRubyのメソッド(`yield`を除く)を呼び出すことができないため、
ほぼ全ての場合にlocalsを指定する必要があるでしょう:
2013-03-04 16:25:59 +00:00
radius :index, :locals => { :key => 'value' }
2013-03-04 16:25:59 +00:00
### Markaby テンプレート
Markabyテンプレートを使うにはmarkabyライブラリが必要です:
2013-03-04 16:25:59 +00:00
# markabyを読み込みます
require 'markaby'
2013-03-04 16:25:59 +00:00
get '/' do
markaby :index
end
2013-03-04 16:25:59 +00:00
`./views/index.mab`を表示します。
2013-03-04 16:25:59 +00:00
### RABL テンプレート
2012-06-01 02:22:06 +00:00
RABLテンプレートを使うにはrablライブラリが必要です:
2013-03-04 16:25:59 +00:00
# rablを読み込みます
require 'rabl'
2012-06-01 02:22:06 +00:00
2013-03-04 16:25:59 +00:00
get '/' do
rabl :index
end
2012-06-01 02:22:06 +00:00
2013-03-04 16:25:59 +00:00
`./views/index.rabl`を表示します。
2012-06-01 02:22:06 +00:00
2013-03-04 16:25:59 +00:00
### Slim テンプレート
2010-11-05 12:59:49 +00:00
Slimテンプレートを使うにはslimライブラリが必要です:
2013-03-04 16:25:59 +00:00
# slimを読み込みます
require 'slim'
2010-11-05 12:59:49 +00:00
2013-03-04 16:25:59 +00:00
get '/' do
slim :index
end
2010-11-05 12:59:49 +00:00
2013-03-04 16:25:59 +00:00
`./views/index.slim`を表示します。
2010-11-05 12:59:49 +00:00
2013-03-04 16:25:59 +00:00
### Creole テンプレート
2011-04-15 09:51:35 +00:00
Creoleテンプレートを使うにはcreoleライブラリが必要です:
2013-03-04 16:25:59 +00:00
# creoleを読み込みます
require 'creole'
2011-04-15 09:51:35 +00:00
2013-03-04 16:25:59 +00:00
get '/' do
creole :index
end
2011-04-15 09:51:35 +00:00
2013-03-04 16:25:59 +00:00
`./views/index.creole`を表示します。
2011-04-15 09:51:35 +00:00
2013-03-04 16:25:59 +00:00
### CoffeeScript テンプレート
2013-03-04 16:25:59 +00:00
CoffeeScriptテンプレートを表示するにはcoffee-scriptライブラリと\`coffee\`バイナリが必要です:
2013-03-04 16:25:59 +00:00
# coffee-scriptを読み込みます
require 'coffee-script'
2013-03-04 16:25:59 +00:00
get '/application.js' do
coffee :application
end
2013-03-04 16:25:59 +00:00
`./views/application.coffee`を表示します。
2013-03-04 16:25:59 +00:00
### インラインテンプレート
2013-03-04 16:25:59 +00:00
get '/' do
haml '%div.title Hello World'
end
文字列をテンプレートとして表示します。
2013-03-04 16:25:59 +00:00
### テンプレート内で変数にアクセスする
2013-03-04 16:25:59 +00:00
テンプレートはルートハンドラと同じコンテキストの中で評価されます。.
ルートハンドラでセットされたインスタンス変数は
テンプレート内で直接使うことができます。
2013-03-04 16:25:59 +00:00
get '/:id' do
@foo = Foo.find(params[:id])
haml '%h1= @foo.name'
end
ローカル変数を明示的に定義することもできます。
2013-03-04 16:25:59 +00:00
get '/:id' do
foo = Foo.find(params[:id])
haml '%h1= foo.name', :locals => { :foo => foo }
end
このやり方は他のテンプレート内で部分テンプレートとして表示する時に典型的に使用されます。
2013-03-04 16:25:59 +00:00
### ファイル内テンプレート
テンプレートはソースファイルの最後で定義することもできます。
2013-03-04 16:25:59 +00:00
require 'rubygems'
require 'sinatra'
2013-03-04 16:25:59 +00:00
get '/' do
haml :index
end
2013-03-04 16:25:59 +00:00
__END__
2013-03-04 16:25:59 +00:00
@@ layout
%html
= yield
2013-03-04 16:25:59 +00:00
@@ index
%div.title Hello world!!!!!
2013-03-04 16:25:59 +00:00
注意:
sinatraをrequireするファイル内で定義されたファイル内テンプレートは自動的に読み込まれます。
他のファイルで定義されているテンプレートを使うには
`enable :inline_templates`を明示的に呼んでください。
2013-03-04 16:25:59 +00:00
### 名前付きテンプレート
2013-03-04 16:25:59 +00:00
テンプレートはトップレベルの`template`メソッドで定義することができます。
2013-03-04 16:25:59 +00:00
template :layout do
"%html\n =yield\n"
end
2013-03-04 16:25:59 +00:00
template :index do
'%div.title Hello World!'
end
2013-03-04 16:25:59 +00:00
get '/' do
haml :index
end
「layout」というテンプレートが存在する場合、そのテンプレートファイルは他のテンプレートが
2013-03-04 16:25:59 +00:00
表示される度に使用されます。`:layout => false`することでlayoutsを無効にできます。
2013-03-04 16:25:59 +00:00
get '/' do
haml :index, :layout => !request.xhr?
end
2013-03-04 16:25:59 +00:00
## ヘルパー
2013-03-04 16:25:59 +00:00
トップレベルの`helpers`を使用してルートハンドラやテンプレートで使うヘルパメソッドを
定義できます。
2013-03-04 16:25:59 +00:00
helpers do
def bar(name)
"#{name}bar"
end
end
2013-03-04 16:25:59 +00:00
get '/:name' do
bar(params[:name])
end
2013-03-04 16:25:59 +00:00
## フィルタ
beforeフィルタはリクエストされたコンテキストを実行する前に評価され、
リクエストとレスポンスを変更することができます。フィルタ内でセットされた
インスタンス変数はルーティングとテンプレートで使用できます。
2013-03-04 16:25:59 +00:00
before do
@note = 'Hi!'
request.path_info = '/foo/bar/baz'
end
2013-03-04 16:25:59 +00:00
get '/foo/*' do
@note #=> 'Hi!'
params[:splat] #=> 'bar/baz'
end
afterフィルタは同じコンテキストにあるリクエストの後に評価され、
同じくリクエストとレスポンスを変更することができます。
beforeフィルタとルートで設定されたインスタンス変数は、
afterフィルタからアクセスすることができます:
2013-03-04 16:25:59 +00:00
after do
puts response.status
end
フィルタにはオプションとしてパターンを渡すことができ、
この場合はリクエストのパスがパターンにマッチした場合のみフィルタが評価されます:
2013-03-04 16:25:59 +00:00
before '/protected/*' do
authenticate!
end
2013-03-04 16:25:59 +00:00
after '/create/:slug' do |slug|
session[:last_slug] = slug
end
2013-03-04 16:25:59 +00:00
## 強制終了
ルートかbeforeフィルタ内で直ちに実行を終了する方法:
2013-03-04 16:25:59 +00:00
halt
ステータスを指定することができます:
2013-03-04 16:25:59 +00:00
halt 410
2013-03-04 16:25:59 +00:00
body部を指定することもできます …
2013-03-04 16:25:59 +00:00
halt 'ここにbodyを書く'
2013-03-04 16:25:59 +00:00
ステータスとbody部を指定する …
2013-03-04 16:25:59 +00:00
halt 401, '立ち去れ!'
ヘッダを指定:
2013-03-04 16:25:59 +00:00
halt 402, {'Content-Type' => 'text/plain'}, 'リベンジ'
2013-03-04 16:25:59 +00:00
## パッシング(Passing)
2013-03-04 16:25:59 +00:00
ルートは`pass`を使って次のルートに飛ばすことができます:
2013-03-04 16:25:59 +00:00
get '/guess/:who' do
pass unless params[:who] == 'Frank'
"見つかっちゃった!"
end
2013-03-04 16:25:59 +00:00
get '/guess/*' do
"はずれです!"
end
ルートブロックからすぐに抜け出し、次にマッチするルートを実行します。
マッチするルートが見当たらない場合は404が返されます。
2013-03-04 16:25:59 +00:00
## リクエストオブジェクトへのアクセス
受信するリクエストオブジェクトは、\`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.bodyの長さ
request.media_type # request.bodyのメディアタイプ
request.host # "example.com"
request.get? # true (他の動詞についても同様のメソッドあり)
request.form_data? # false
request["SOME_HEADER"] # SOME_HEADERヘッダの値
request.referer # クライアントのリファラまたは'/'
request.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 # Rackによって渡された生のenvハッシュ
end
`script_name`や`path_info`などのオプションは次のように利用することもできます:
before { request.path_info = "/" }
get "/" do
"全てのリクエストはここに来る"
end
`request.body`はIOまたはStringIOのオブジェクトです:
post "/api" do
request.body.rewind # 既に読まれているときのため
data = JSON.parse request.body.read
"Hello #{data['name']}!"
end
## 設定
どの環境でも起動時に1回だけ実行されます。
2013-03-04 16:25:59 +00:00
configure do
...
end
2013-03-04 16:25:59 +00:00
環境(RACK\_ENV環境変数)が`:production`に設定されている時だけ実行する方法:
2013-03-04 16:25:59 +00:00
configure :production do
...
end
2013-03-04 16:25:59 +00:00
環境が`:production`か`:test`の場合に設定する方法:
2013-03-04 16:25:59 +00:00
configure :production, :test do
...
end
2013-03-04 16:25:59 +00:00
## エラーハンドリング
エラーハンドラーはルートコンテキストとbeforeフィルタ内で実行します。
2013-03-04 16:25:59 +00:00
`haml`、`erb`、`halt`などを使うこともできます。
2013-03-04 16:25:59 +00:00
### Not Found
2013-03-04 16:25:59 +00:00
`Sinatra::NotFound`が起きた時か レスポンスのステータスコードが
404の時に`not_found`ハンドラーが発動します。
2013-03-04 16:25:59 +00:00
not_found do
'ファイルが存在しません'
end
2013-03-04 16:25:59 +00:00
### エラー
2013-03-04 16:25:59 +00:00
`error`
ハンドラーはルートブロックかbeforeフィルタ内で例外が発生した時はいつでも発動します。
例外オブジェクトはRack変数`sinatra.error`から取得できます。
2013-03-04 16:25:59 +00:00
error do
'エラーが発生しました。 - ' + env['sinatra.error'].name
end
エラーをカスタマイズする場合は、
2013-03-04 16:25:59 +00:00
error MyCustomError do
'エラーメッセージ...' + env['sinatra.error'].message
end
と書いておいて,下記のように呼び出します。
2013-03-04 16:25:59 +00:00
get '/' do
raise MyCustomError, '何かがまずかったようです'
end
そうするとこうなります:
2013-03-04 16:25:59 +00:00
エラーメッセージ... 何かがまずかったようです
あるいは、ステータスコードに対応するエラーハンドラを設定することもできます:
2013-03-04 16:25:59 +00:00
error 403 do
'Access forbidden'
end
2013-03-04 16:25:59 +00:00
get '/secret' do
403
end
範囲指定もできます:
2013-03-04 16:25:59 +00:00
error 400..510 do
'Boom'
end
2013-03-04 16:25:59 +00:00
開発環境として実行している場合、Sinatraは特別な`not_found`と`error`ハンドラーを
インストールしています。
2013-03-04 16:25:59 +00:00
## MIMEタイプ
2013-03-04 16:25:59 +00:00
`send_file`か静的ファイルを使う時、Sinatraが理解でいないMIMEタイプがある場合があります。
その時は `mime_type` を使ってファイル拡張子毎に登録して下さい。
2013-03-04 16:25:59 +00:00
mime_type :foo, 'text/foo'
2013-03-04 16:25:59 +00:00
これはcontent\_typeヘルパで利用することができます:
2013-03-04 16:25:59 +00:00
content_type :foo
2013-03-04 16:25:59 +00:00
## Rackミドルウェア
2013-03-04 16:25:59 +00:00
[SinatraはRack](http://rack.rubyforge.org/)フレームワーク用の
最小限の標準インターフェース
上で動作しています。Rack中でもアプリケーションデベロッパー
向けに一番興味深い機能はミドルウェア(サーバとアプリケーション間に介在し、モニタリング、HTTPリクエストとレスポンス
の手動操作ができるなど、一般的な機能のいろいろなことを提供するもの)をサポートすることです。
2013-03-04 16:25:59 +00:00
Sinatraではトップレベルの`use`
メソッドを使ってRackにパイプラインを構築します。
2013-03-04 16:25:59 +00:00
require 'sinatra'
require 'my_custom_middleware'
2013-03-04 16:25:59 +00:00
use Rack::Lint
use MyCustomMiddleware
2013-03-04 16:25:59 +00:00
get '/hello' do
'Hello World'
end
2013-03-04 16:25:59 +00:00
`use`
[Rack::Builder](http://rack.rubyforge.org/doc/classes/Rack/Builder.html)
DSLで定義されていることと全て一致します。 例えば `use`
メソッドはブロック構文のように複数の引数を受け取ることができます。
2013-03-04 16:25:59 +00:00
use Rack::Auth::Basic do |username, password|
username == 'admin' && password == 'secret'
end
Rackはログ、デバッギング、URLルーティング、認証、セッションなどいろいろな機能を備えた標準的ミドルウェアです。
2013-03-04 16:25:59 +00:00
Sinatraはその多くのコンポーネントを自動で使うよう基本設定されているため、`use`で明示的に指定する必要はありません。
2013-03-04 16:25:59 +00:00
## テスト
SinatraでのテストはRack-basedのテストライブラリかフレームワークを使って書くことができます。
2013-03-04 16:25:59 +00:00
[Rack::Test](http://gitrdoc.com/brynary/rack-test)
をおすすめします。やり方:
2013-03-04 16:25:59 +00:00
require 'my_sinatra_app'
require 'rack/test'
2013-03-04 16:25:59 +00:00
class MyAppTest < Test::Unit::TestCase
include Rack::Test::Methods
2013-03-04 16:25:59 +00:00
def app
Sinatra::Application
end
2013-03-04 16:25:59 +00:00
def test_my_default
get '/'
assert_equal 'Hello World!', last_response.body
end
2013-03-04 16:25:59 +00:00
def test_with_params
get '/meet', :name => 'Frank'
assert_equal 'Hello Frank!', last_response.body
end
2013-03-04 16:25:59 +00:00
def test_with_rack_env
get '/', {}, 'HTTP_USER_AGENT' => 'Songbird'
assert_equal "あなたはSongbirdを使ってますね!", last_response.body
end
end
注意: ビルトインのSinatra::TestモジュールとSinatra::TestHarnessクラスは
0.9.2リリース以降、廃止予定になっています。
2013-03-04 16:25:59 +00:00
## Sinatra::Base - ミドルウェア、ライブラリ、 モジュラーアプリ
トップレベル(グローバル領域)上でいろいろ定義していくのは軽量アプリならうまくいきますが、
RackミドルウェアやRails metal、サーバのコンポーネントを含んだシンプルな
ライブラリやSinatraの拡張プログラムを考慮するような場合はそうとは限りません。
トップレベルのDSLがネームスペースを汚染したり、設定を変えてしまうこと(例:./publicや./view)がありえます。
そこでSinatra::Baseの出番です。
2013-03-04 16:25:59 +00:00
require 'sinatra/base'
2013-03-04 16:25:59 +00:00
class MyApp < Sinatra::Base
set :sessions, true
set :foo, 'bar'
2013-03-04 16:25:59 +00:00
get '/' do
'Hello world!'
end
end
このMyAppは独立したRackコンポーネントで、RackミドルウェアやRackアプリケーション
2013-03-04 16:25:59 +00:00
Rails metalとして使用することができます。`config.ru`ファイル内で `use`
か、または `run`
でこのクラスを指定するか、ライブラリとしてサーバコンポーネントをコントロールします。
2013-03-04 16:25:59 +00:00
MyApp.run! :host => 'localhost', :port => 9090
Sinatra::Baseのサブクラスで使えるメソッドはトップレベルのDSLを経由して確実に使うことができます。
ほとんどのトップレベルで記述されたアプリは、以下の点を修正することでSinatra::Baseコンポーネントに変えることができます。
2013-03-04 16:25:59 +00:00
- `sinatra`の代わりに`sinatra/base`を読み込む
(そうしない場合、SinatraのDSLメソッドの全てがメインネームスペースにインポートされます)
2013-03-04 16:25:59 +00:00
- ルート、エラーハンドラー、フィルター、オプションをSinatra::Baseのサブクラスに書く
`Sinatra::Base`
はまっさらです。ビルトインサーバを含む、ほとんどのオプションがデフォルト
で無効になっています。オプション詳細については[Options and
Configuration](http://sinatra.github.com/configuration.html)
をご覧下さい。
2013-03-04 16:25:59 +00:00
補足:
SinatraのトップレベルDSLはシンプルな委譲(delgation)システムで実装されています。
`Sinatra::Application`クラス(Sinatra::Baseの特別なサブクラス)は、トップレベルに送られる
:get、 :put、 :post、:delete、 :before、:error、:not\_found、
:configure、:set messagesのこれら 全てを受け取ります。
詳細を閲覧されたい方はこちら(英語): [Sinatra::Delegator
mixin](http://github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb#L1064)
[included into the main
namespace](http://github.com/sinatra/sinatra/blob/master/lib/sinatra/main.rb#L25).
2013-03-04 16:25:59 +00:00
### Sinatraをミドルウェアとして利用する
Sinatraは他のRackミドルウェアを利用することができるだけでなく、
全てのSinatraアプリケーションは、それ自体ミドルウェアとして別のRackエンドポイントの前に追加することが可能です。
2013-03-04 16:25:59 +00:00
このエンドポイントには、別の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
2013-03-04 16:25:59 +00:00
class MyApp < Sinatra::Base
# middleware will run before filters
use LoginScreen
before do
unless session['user_name']
halt "Access denied, please <a href='/login'>login</a>."
end
end
2013-03-04 16:25:59 +00:00
get('/') { "Hello #{session['user_name']}." }
end
2013-03-04 16:25:59 +00:00
## スコープとバインディング
現在のスコープはどのメソッドや変数が利用可能かを決定します。
2013-03-04 16:25:59 +00:00
### アプリケーション/クラスのスコープ
全てのSinatraアプリケーションはSinatra::Baseのサブクラスに相当します。
2013-03-04 16:25:59 +00:00
もしトップレベルDSLを利用しているならば(`require 'sinatra'`)このクラスはSinatra::Applicationであり、
そうでなければ、あなたが明示的に作成したサブクラスです。
2013-03-04 16:25:59 +00:00
クラスレベルでは\`get\`や\`before\`のようなメソッドを持っています。
しかし\`request\`オブジェクトや\`session\`には、全てのリクエストのために1つのアプリケーションクラスが存在するためアクセスできません。
2013-03-04 16:25:59 +00:00
\`set\`によって作られたオプションはクラスレベルのメソッドです:
class MyApp < Sinatra::Base
# Hey, I'm in the application scope!
set :foo, 42
foo # => 42
2013-03-04 16:25:59 +00:00
get '/foo' do
# Hey, I'm no longer in the application scope!
end
end
次の場所ではアプリケーションスコープバインディングを持ちます:
2013-03-04 16:25:59 +00:00
- アプリケーションのクラス本体
- 拡張によって定義されたメソッド
- \`helpers\`に渡されたブロック
- \`set\`の値として使われるProcまたはブロック
このスコープオブジェクト(クラス)は次のように利用できます:
2013-03-04 16:25:59 +00:00
- configureブロックに渡されたオブジェクト経由(`configure { |c| ... }`)
- リクエストスコープの中での\`settings\`
2013-03-04 16:25:59 +00:00
### リクエスト/インスタンスのスコープ
やってくるリクエストごとに、あなたのアプリケーションクラスの新しいインスタンスが作成され、全てのハンドラブロックがそのスコープで実行されます。
2013-03-04 16:25:59 +00:00
このスコープの内側からは\`request\`や\`session\`オブジェクトにアクセスすることができ、\`erb\`や\`haml\`のような表示メソッドを呼び出すことができます。
リクエストスコープの内側からは、\`settings\`ヘルパによってアプリケーションスコープにアクセスすることができます。
class MyApp < Sinatra::Base
# Hey, I'm in the application scope!
get '/define_route/:name' do
# Request scope for '/define_route/:name'
@value = 42
settings.get("/#{params[:name]}") do
# Request scope for "/#{params[:name]}"
@value # => nil (not the same request)
end
"Route defined!"
end
end
次の場所ではリクエストスコープバインディングを持ちます:
2013-03-04 16:25:59 +00:00
- get/head/post/put/delete ブロック
- before/after フィルタ
- helper メソッド
- テンプレート/ビュー
2013-03-04 16:25:59 +00:00
### デリゲートスコープ
デリゲートスコープは、単にクラススコープにメソッドを転送します。
しかしながら、クラスのバインディングを持っていないため、クラススコープと全く同じふるまいをするわけではありません:
2013-03-04 16:25:59 +00:00
委譲すると明示的に示されたメソッドのみが利用可能であり、またクラススコープと変数/状態を共有することはできません(注:
異なった\`self\`を持っています)。
`Sinatra::Delegator.delegate :method_name`を呼び出すことによってデリゲートするメソッドを明示的に追加することができます。
次の場所ではデリゲートスコープを持ちます:
2013-03-04 16:25:59 +00:00
- もし`require "sinatra"`しているならば、トップレベルバインディング
2013-03-04 16:25:59 +00:00
- \`Sinatra::Delegator\` mixinでextendされたオブジェクト
2013-03-04 16:25:59 +00:00
コードをご覧ください: ここでは [Sinatra::Delegator
mixin](http://github.com/sinatra/sinatra/blob/ceac46f0bc129a6e994a06100aa854f606fe5992/lib/sinatra/base.rb#L1128)
は[main
名前空間にincludeされています](http://github.com/sinatra/sinatra/blob/ceac46f0bc129a6e994a06100aa854f606fe5992/lib/sinatra/main.rb#L28).
## コマンドライン
Sinatraアプリケーションは直接実行できます。
2013-03-04 16:25:59 +00:00
ruby myapp.rb [-h] [-x] [-e ENVIRONMENT] [-p PORT] [-o HOST] [-s HANDLER]
オプション:
2013-03-04 16:25:59 +00:00
-h # ヘルプ
-p # ポート指定(デフォルトは4567)
-o # ホスト指定(デフォルトは0.0.0.0)
-e # 環境を指定 (デフォルトはdevelopment)
-s # rackserver/handlerを指定 (デフォルトはthin)
-x # mutex lockを付ける (デフォルトはoff)
2013-03-04 16:25:59 +00:00
## 最新開発版について
Sinatraの開発版を使いたい場合は、ローカルに開発版を落として、
2013-03-04 16:25:59 +00:00
`LOAD_PATH`の`sinatra/lib`ディレクトリを指定して実行して下さい。
2013-03-04 16:25:59 +00:00
cd myapp
git clone git://github.com/sinatra/sinatra.git
ruby -Isinatra/lib myapp.rb
2013-03-04 16:25:59 +00:00
`sinatra/lib`ディレクトリをアプリケーションの`LOAD_PATH`に追加する方法もあります。
2013-03-04 16:25:59 +00:00
$LOAD_PATH.unshift File.dirname(__FILE__) + '/sinatra/lib'
require 'rubygems'
require 'sinatra'
2013-03-04 16:25:59 +00:00
get '/about' do
"今使ってるバージョンは" + Sinatra::VERSION
end
Sinatraのソースを更新する方法:
2013-03-04 16:25:59 +00:00
cd myproject/sinatra
git pull
2013-03-04 16:25:59 +00:00
## その他
日本語サイト
2013-03-04 16:25:59 +00:00
- [Greenbear Laboratory
Rack日本語マニュアル](http://mono.kmc.gr.jp/~yhara/w/?RackReferenceJa)
- Rackの日本語マニュアル
英語サイト
2013-03-04 16:25:59 +00:00
- [プロジェクトサイト](http://sinatra.github.com/) - ドキュメント、
ニュース、他のリソースへのリンクがあります。
- [プロジェクトに参加(貢献)する](http://sinatra.github.com/contributing.html)
- バグレポート パッチの送信、サポートなど
- [Issue tracker](http://github.com/sinatra/sinatra/issues) -
チケット管理とリリース計画
- [Twitter](http://twitter.com/sinatra)
- [メーリングリスト](http://groups.google.com/group/sinatrarb)
- [IRC: \#sinatra](irc://chat.freenode.net/#sinatra) on
[freenode.net](http://freenode.net)