今さらSinatra最低限メモ

今度は Sinatra. 次もすぐに動かせるように公式のドキュメントを圧縮する感じで、自分の欲しい情報だけ。アプリを書く以前のレベルで、まずはページを表示できる状態を目指す。

実は昨日の kanazawa.js の成果その2

環境

今回の環境は

  • MacOSX 10.5
  • Ruby 1.8.7
  • Sinatra 1.1.3
  • Ruby 1.9.2
  • Sinatra 1.2.0

で確認した。Sinatra のバージョンが合ってないことに特に意味はない。

インストール

(ry

動かし方

1ファイルの場合は

$ ruby app.rb

でもよい。例の感じで中に

require 'rubygems' unless defined? ::Gem
require 'sinatra'

get '/' do
  'Hello, World'
end

で終了。デフォルトで port 4567 で起きる。

ちなみにこれだけで response header とこの文字列だけの response body が返る。PHPer 的には print や echo で出力したくなるけどそれは間違い。これは

get '/' do
  return 'Hello, World'
end

の return を省略してるだけ。return が response になる。rack の header を省略できると思えばいいはず。

設定とか分離したい

rack の流儀に則って config.ru を用意(別名でもいいけど)。

config.ru

require 'rubygems' unless defined? ::Gem
require File.dirname( __FILE__ ) + '/app'

run Sinatra::Application

app.rb

require 'sinatra'

get '/' do
  'Hello, World !'
end

この場合は rackup する。1

$ rackup

デフォルトで port 9292 になる。rack の流儀で変更可能。

$ rackup --port 80

※ ただし Un*x なシステムでは 1024 以下は特権ポート。のはず。

Handler を明示すれば option を与えられるけど、Handler を与えない方針なので以上。

自動でReload

mod_php や Rails の development 環境に慣れてしまったのでこれがないとやってられない。方法は3つ。

  • Rack::Reloader
  • Shotgun
  • Sinatra::Reloader

What happened to reloading in Sinatra 0.9.2? - Sinatra: Frequently Asked Questions

Rack::Reloader

普通の Rack Middleware

use Rack::Reloader

すればオッケー。でもちゃんと動かないらしい。動いてるように見えるけど、そうとは限らないということか。却下。

Shotgun

rtomayko/shotgun - GitHub

shotgun の名前がインパクトがあってよく覚えてたんだけど、今 Sinatra のサイトで読むといちばん遅いのと、fork を使うので JRuby や Windows で動かないとのこと。あやや。

インストールはもちろん

gem install shotgun

これは普通のアプリの起動にも使えるし、

shotgun app.rb

rackup 代わりにもそのまま使える。

shotgun [config.ru]

今度は port はデフォルトで 9393 になる。

Sinatra::Reloader

gem install sinatra-reloader

個人的には予想以上に依存が多い。

if development?
  require 'sinatra/reloader'
  Sinatra.register Sinatra::Reloader
end

で使える。Rack Middleware の要領で use ってやったら怒られた。Sinatra Extension と Rack Middleware は違うのね。

あと当たり前だけど

reloaderに関する書き換えを行うときは再起動した方がいいよ。

ディレクトリ構成とsetによる設定

project/
 ├── app.rb
 ├── config.ru
 ├── public/
 │     └── javascripts/
 │             ├── LAB.js
 │             ├── application.js
 │             ├── jquery-1.5.1.min.js
 │             └── jquery.Router.js
 └── views/
        ├── hello.erubis
        ├── index.erubis
        └── layout.erubis

Rails流とちょっと違う。

この public, views はそれぞれ以下のように設定できる。

README.rdoc

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

要するにアプリケーションのファイルを基準にして自分で決めたきゃ決めろと。この設定方法は Capistrano に似てるなぁ。

何が設定できるかはここを見るといい。

Sinatra: Configuring Settings

root も変更できる。

テンプレートの選択とrender

基本系

get '/' do
  erb :index
end

こんな感じ。これで

  • index.erb を探して
  • erb でレンダリング

という意味になる。拡張子の変更はできるのかなぁ。できないような気がする。中で render メソッドを読んでるんだけど、ちゃんと追いかけると何か分かるかも。

render は最後に

erb :index

って書き方だけだと index.erb を表示用に使うよ、っていう宣言に見えちゃうんだけど、これはれっきとした render メソッドの呼び出しなので、処理はこの前に書くこと。と言うか

erb :index とかは最後に書け

の方が分かりやすいか。

erubis でHTMLのエスケープをデフォルトに

Rails 3 以降デビューなのでこれがないとやってられない。

require 'erubis'

set :erubis, :escape_html => true

get '/' do
  erubis :index
end

こんだけ。

オブジェクトの割り当て

これは Rails の View に似ていて(同じ?)、

  • インスタンス変数は直接参照可能
  • ローカル変数は明示的に :locals で割り当て

という方法を採る。

app.rb

get '/' do
  erubis :index, :locals => {:key => value}
end

views/index.erubis

<%= key %>

こんな感じで value が表示できる。

layoutファイル

layout ファイルは

views/layout.#{ENGINE}

になるはず。layout ファイルと個々のテンプレートで種類を変えることができるのかどうか分からない。たぶんしない方がいいと思う。

erubis の「エスケープしない」出力

layout.erubis

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title><%= @title %></title>
  </head>
  <body>
    <h1><%= @title %></h1>

    <%== yield %>

  </body>
</html>

こういう風にしとくと個々の

erubis :index

などの中身に HTML をそのまま書くことができる。

<%== %>

が決め手。

参考

  1. Handler を直接 config.ru に書く方法もあるんだけど、それだと環境を変えるためにはいちいち書き直さなきゃいけないから嬉しくないと思う。 

More