public
Fork of bmizerany/sinatra
Description: Classy web-development dressed in a DSL (official / canonical repo)
Homepage: http://sinatra.github.com
Clone URL: git://github.com/sinatra/sinatra.git
sr (author)
Wed Nov 04 17:41:06 -0800 2009
commit  f3755308b94a5861e1f2b4c38d15b166d0b991ef
tree    a6d3336fa166f5f73422cffb806c8774c5966378
parent  6d8b333af44886016eeedda18da2855549beffff
sinatra / README.jp.rdoc
100644 553 lines (375 sloc) 17.801 kb

Sinatra

SinatraはRubyで下記のような最小労力で手早くウェブアプリケーションを作成するためのDSLです。

  # myapp.rb
  require 'rubygems'
  require 'sinatra'
  get '/' do
    'Hello world!'
  end

gemをインストールして動かしてみる。

  sudo gem install sinatra
  ruby myapp.rb

localhost:4567 を見る。

ルート

Sinatraでは、ルートはHTTPメソッドとURLマッチングパターンがペアになっています。 ルートはブロックに結び付けられています。

  get '/' do
    .. 何か見せる ..
  end

  post '/' do
    .. 何か生成する ..
  end

  put '/' do
    .. 何か更新する ..
  end

  delete '/' do
    .. 何か削除する ..
  end

ルートは定義された順番にマッチします。 リクエストに最初にマッチしたルートが呼び出されます。

ルートのパターンは名前付きパラメータを含むことができ、 paramsハッシュで取得できます。

  get '/hello/:name' do
    # matches "GET /hello/foo" and "GET /hello/bar"
    # params[:name] is 'foo' or 'bar'
    "Hello #{params[:name]}!"
  end

また、ブロックパラメータで名前付きパラメータにアクセスすることもできます。

  get '/hello/:name' do |n|
    "Hello #{n}!"
  end

ルートパターンはsplat(またはワイルドカード)を含むこともでき、 params[:splat] で取得できます。

  get '/say/*/to/*' do
    # matches /say/hello/to/world
    params[:splat] # => ["hello", "world"]
  end

  get '/download/*.*' do
    # matches /download/path/to/file.xml
    params[:splat] # => ["path/to/file", "xml"]
  end

正規表現を使ったルート:

  get %r{/hello/([\w]+)} do
    "Hello, #{params[:captures].first}!"
  end

ブロックパラーメータを使用した場合:

  get %r{/hello/([\w]+)} do |c|
    "Hello, #{c}!"
  end

ルートにはユーザエージェントのようなさまざまな条件を含めることができます。

  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

静的ファイル

静的ファイルは./publicディレクトリから配信されます。 :publicオプションを指定することで別の場所を指定することができます。

  set :public, File.dirname(__FILE__) + '/static'

注意: この静的ファイル用のディレクトリ名はURL中に含まれません。 例えば、./public/css/style.cssexample.com/css/style.cssでアクセスできます。

ビュー / テンプレート

テンプレートは./viewsディレクトリ下に配置されています。 他のディレクトリを使用する場合の例:

  set :views, File.dirname(__FILE__) + '/templates'

テンプレートはシンボルを使用して参照させることを覚えておいて下さい。 サブデレクトリでもこの場合は:’subdir/template’のようにします。 レンダリングメソッドは文字列が渡されると、そのまま文字列を出力します。

Haml テンプレート

hamlを使うにはhamlライブラリが必要です:

  ## hamlを読み込みます
  require 'haml'

  get '/' do
    haml :index
  end

./views/index.hamlを表示します。

Haml's options はSinatraの設定でグローバルに設定することができます。 Options and Configurations, を参照してそれぞれ設定を上書きして下さい。

  set :haml, {:format => :html5 } # デフォルトのフォーマットは:xhtml

  get '/' do
    haml :index, :haml_options => {:format => :html4 } # 上書き
  end

Erb テンプレート

  ## erbを読み込みます
  require 'erb'

  get '/' do
    erb :index
  end

./views/index.erbを表示します。

Builder テンプレート

builderを使うにはbuilderライブラリが必要です:

  ## builderを読み込みます
  require 'builder'

  get '/' do
    content_type 'application/xml', :charset => 'utf-8'
    builder :index
  end

./views/index.builderを表示します。

Sass テンプレート

Sassテンプレートを使うにはsassライブラリが必要です:

  ## hamlかsassを読み込みます
  require 'sass'

  get '/stylesheet.css' do
    content_type 'text/css', :charset => 'utf-8'
    sass :stylesheet
  end

./views/stylesheet.sassを表示します。

Sass' options はSinatraの設定でグローバルに設定することができます。 see Options and Configurations, を参照してそれぞれ設定を上書きして下さい。

  set :sass, {:style => :compact } # デフォルトのSass styleは :nested

  get '/stylesheet.css' do
    content_type 'text/css', :charset => 'utf-8'
    sass :stylesheet, :sass_options => {:style => :expanded } # 上書き
  end

インラインテンプレート

  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

このやり方は他のテンプレート内で部分テンプレートとして表示する時に典型的に使用されます。

ファイル内テンプレート

テンプレートはソースファイルの最後で定義することもできます。

  require 'rubygems'
  require 'sinatra'

  get '/' do
    haml :index
  end

  __END__

  @@ layout
  %html
    = yield

  @@ index
  %div.title Hello world!!!!!

注意: sinatraをrequireするファイル内で定義されたファイル内テンプレートは自動的に読み込まれます。 他のファイルで定義されているテンプレートを使うには use_in_file_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.することでlayoutsを無効にできます。

  get '/' do
    haml :index, :layout => !request.xhr?
  end

ヘルパー

トップレベルの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

強制終了

ルートかbeforeフィルタ内で直ちに実行を終了する方法:

  halt

body部を指定することもできます …

  halt 'ここにbodyを書く'

ステータスとbody部を指定する …

  halt 401, '立ち去れ!'

パッシング(Passing)

ルートはpassを使って次のルートに飛ばすことができます:

  get '/guess/:who' do
    pass unless params[:who] == 'Frank'
    "見つかっちゃった!"
  end

  get '/guess/*' do
    "はずれです!"
  end

ルートブロックからすぐに抜け出し、次にマッチするルートを実行します。 マッチするルートが見当たらない場合は404が返されます。

設定

どの環境でも起動時に1回だけ実行されます。

  configure do
    ...
  end

環境変数:production(RACK_ENV環境変数) がセットされている時だけ実行する方法:

  configure :production do
    ...
  end

環境変数:production:testの場合に設定する方法:

  configure :production, :test do
    ...
  end

エラーハンドリング

エラーハンドラーはルートコンテキストとbeforeフィルタ内で実行します。 hamlerbhaltなどを使うこともできます。

Not Found

Sinatra::NotFoundが起きた時か レスポンスのステータスコードが 404の時にnot_foundハンドラーが発動します。

  not_found do
    'ファイルが存在しません'
  end

エラー

error ハンドラーはルートブロックかbeforeフィルタ内で例外が発生した時はいつでも発動します。 block or before filter. 例外オブジェクトはRack変数sinatra.errorから取得されます。

  error do
    'エラーが発生しました。 - ' + env['sinatra.error'].name
  end

エラーをカスタマイズする場合は、

  error MyCustomError do
    'エラーメッセージ...' + request.env['sinatra.error'].message
  end

と書いておいて,下記のように呼び出します。

  get '/' do
    raise MyCustomError, '何かがまずかったようです'
  end

そうするとこうなります:

  エラーメッセージ... 何かがまずかったようです

開発環境として実行している場合、Sinatraは特別なnot_founderrorハンドラーを インストールしています。

MIMEタイプ

send_fileか静的ファイルを使う時、Sinatraが理解でいないMIMEタイプがある場合があります。 その時は mime_type を使ってファイル拡張子毎に登録して下さい。

  mime_type :foo, 'text/foo'

Rackミドルウェア

SinatraはRack 最小限の標準インターフェース 上で動作しています。Rack中でもアプリケーションデベロッパー 向けに一番興味深い機能はミドルウェア(サーバとアプリケーション間に介在し、モニタリング、HTTPリクエストとレスポンス の手動操作ができるなど、一般的な機能のいろいろなことを提供するもの)をサポートすることです。

Sinatraではトップレベルの+user+ メソッドを使ってRackにパイプラインを構築します。

  require 'sinatra'
  require 'my_custom_middleware'

  use Rack::Lint
  use MyCustomMiddleware

  get '/hello' do
    'Hello World'
  end

use Rack::Builder DSLで定義されていることと全て一致します。 例えば use メソッドはブロック構文のように複数の引数を受け取ることができます。

  use Rack::Auth::Basic do |username, password|
    username == 'admin' && password == 'secret'
  end

Rackはログ、デバッギング、URLルーティング、認証、セッションなどいろいろな機能を備えた標準的ミドルウェアです。 Sinatraはその多くのコンポーネントを自動で使うよう基本設定されているため、+use+で明示的に指定する必要はありません。

テスト

SinatraでのテストはRack-basedのテストライブラリかフレームワークを使って書くことができます。 Rack::Test をおすすめします。やり方:

  require 'my_sinatra_app'
  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 "あなたはSongbirdを使ってますね!", last_response.body
    end
  end

注意: ビルトインのSinatra::TestモジュールとSinatra::TestHarnessクラスは 0.9.2リリース以降、廃止予定になっています。

Sinatra::Base - ミドルウェア、ライブラリ、 モジュラーアプリ

トップレベル(グローバル領域)上でいろいろ定義していくのは軽量アプリならうまくいきますが、 RackミドルウェアやRails metal、サーバのコンポーネントを含んだシンプルな ライブラリやSinatraの拡張プログラムを考慮するような場合はそうとは限りません。 トップレベルのDSLがネームスペースを汚染したり、設定を変えてしまうこと(例:./publicや./view)がありえます。 そこでSinatra::Baseの出番です。

  require 'sinatra/base'

  class MyApp < Sinatra::Base
    set :sessions, true
    set :foo, 'bar'

    get '/' do
      'Hello world!'
    end
  end

このMyAppは独立したRackコンポーネントで、RackミドルウェアやRackアプリケーション Rails metalとして使用することができます。config.ruファイル内で use か、または run でこのクラスを指定するか、ライブラリとしてサーバコンポーネントをコントロールします。

   MyApp.run! :host => 'localhost', :port => 9090

Sinatra::Baseのサブクラスで使えるメソッドはトップレベルのDSLを経由して確実に使うことができます。 ほとんどのトップレベルで記述されたアプリは、以下の2点を修正することでSinatra::Baseコンポーネントに変えることができます。

  • +sinatra+の代わりにsinatra/baseを読み込む

(そうしない場合、SinatraのDSLメソッドの全てがメインネームスペースにインポートされます)

  • ルート、エラーハンドラー、フィルター、オプションをSinatra::Baseのサブクラスに書く

Sinatra::Base はまっさらです。ビルトインサーバを含む、ほとんどのオプションがデフォルト で無効になっています。オプション詳細についてはOptions and Configuration をご覧下さい。

補足: SinatraのトップレベルDSLはシンプルな委譲(delgation)システムで実装されています。 Sinatra::Applicationクラス(Sinatra::Baseの特別なサブクラス)は、トップレベルに送られる :get、 :put、 :post、:delete、 :before、:error、:not_found、 :configure、:set messagesのこれら 全てを受け取ります。 詳細を閲覧されたい方はこちら(英語): Sinatra::Delegator mixin included into the main namespace.

コマンドライン

Sinatraアプリケーションは直接実行できます。

  ruby myapp.rb [-h] [-x] [-e ENVIRONMENT] [-p PORT] [-s HANDLER]

オプション:

  -h # ヘルプ
  -p # ポート指定(デフォルトは4567)
  -e # 環境を指定 (デフォルトはdevelopment)
  -s # rackserver/handlerを指定 (デフォルトはthin)
  -x # mutex lockを付ける (デフォルトはoff)

最新開発版について

Sinatraの開発版を使いたい場合は、ローカルに開発版を落として、 LOAD_PATHsinatra/libディレクトリを指定して実行して下さい。

  cd myapp
  git clone git://github.com/sinatra/sinatra.git
  ruby -Isinatra/lib myapp.rb

sinatra/libディレクトリをto theLOAD_PATHに追加する方法もあります。

  $LOAD_PATH.unshift File.dirname(__FILE__) + '/sinatra/lib'
  require 'rubygems'
  require 'sinatra'

  get '/about' do
    "今使ってるバージョンは" + Sinatra::VERSION
  end

Sinatraのソースを更新する方法:

  cd myproject/sinatra
  git pull

その他

日本語サイト

英語サイト