unoh.github.com

Sinatra気に入った

Fri May 15 02:12:16 -0700 2009

先日、まちつく!正式リリースになりました。よろしければ是非携帯でアクセスして遊んでみてください。

おはようございます。内田です。

今までRailsを使うほどでも無いアプリはオレオレフレームワークで作ってたのですが、最近巷で流行ってるsinatraのコードを読んでみたら必要十分な機能があり、センスも良く、とても気に入りました。

今回は公式ドキュメントの流れで、使いそうな機能をまとめてみました

一番簡単な例

sudo gem install sinatra
# app.rb
require 'rubygems'
require 'sinatra'

get '/' do
  'Hello, world'
end
ruby app.rb
curl http://localhost:4567/

Routes

HTTPメソッドにURLとブロックを渡します


get ‘/’ do
end
post ‘/’ do
end
put ‘/’ do
end
delete ‘/’ do
end

パラメータを含めたURLも可能


get ‘/hello/:name’ do
“Hello #{params[:name]}”
end

上記パラメータはブロック引数でも取れる


get ‘/hello/:name’ do |n|
“Hello #{n}”
end

ワイルドカードもつかえます


get ‘/say//to/’ do

  1. /say/hello/to/worldにアクセス
    params[“splat”] # => [“hello”, "world]
    end

?つきのパラメータやPOST等のパラメータはparams[:xxx]で取得できるよ

アプリケーションファイルは複数に分けることが可能。
読み込みにはrequireを使わずにloadを使うとdevelopmentモードの時に便利


require ‘rubygems’
require ‘sinatra’
get ‘/’ do
“Hello world”
end
load ‘more_routes.rb’

# more_routes.rb
get '/foo' do
  "Foo"
end

Handlers

Redirect


redirect ‘/’
redirect ‘http://www.google.co.jp’
redirect ‘/’, 303
redirect ‘/’, 307

Session
クッキーベースのセッション
有効にするにはTOPレベルか、configureブロックに書く


enable :sessions
get ‘/’ do
session[“count”] ||= 0
session[“count”] += 1
“count: #{session[‘count’]}”
end

Status
通常では200番のステータスコードになるがstatusメソッドをつかうと変更できる


get ‘/’ do
status 404
“Not found”
end

Filters

イベントの前に実行される


before do
end

before do
  new_params = {}
  params.each_pair do |full_key, value|
    this_param = new_params
    split_keys = full_key.split(/\]\[|\]|\[/)
    split_keys.each_index do |index|
      break if split_keys.length == index + 1
      this_param[split_keys[index]] ||= {}
      this_param = this_param[split_keys[index]]
   end
   this_param[split_keys.last] = value
  end
  request.params.replace new_params
end
<form>
  <input ... name="post[title]" />
  <input ... name="post[body]" />
  <input ... name="post[author]" />
</form>
{"post"=>{ "title"=>"", "body"=>"", "author"=>"" }}

views

Template Languages
viewファイルはroot/viewsに置きましょう
Haml,Sass,Erb,Builderがつかえる

  1. app.rb
    get ‘/’ do
    erb :index # views/index.erb
    sass :styles # views/styles.sass
    haml :index # views/index.haml
    builder :index # views/index.builder
    end

builderはブロックを使ってRSSを出力できたりする
サンプルプログラムが公式にあります。

Layouts
root/views/layout.{erb|haml|builder}




<%= yield %>

使いたくないときは


get ‘/’ do
erb :index, layout => false
end

アプリケーションと同じファイルにviewが書ける
が、個人的には使わない。公式参照

Models

sinatraはmodelを提供してないので、好きなのを使うとよろし
Sequelを使ってみる。

  1. app.rb
    require ‘rubygems’
    require ‘sinatra’
    require ‘sequel’
    Sequel::Model.plugin(:schema)
    sequel.connect(‘sqlite://test.db’)
    class Items < Sequel::Model
    unless table_exista?
    set_schema do
    primary_key :id
    string :name
    timestamp :created_at
    end
    create_table
    end
    end
    get ‘/’ do
    @items = Items.all
    erb :index
    end
# views/index.erb
<% for item in @items %>
  <div><%= item.name %></div>
<% end %>

DatamapperやActiveRecordを使いたい場合は公式参照

API的なJSONでも出力してみる


require ‘json’
get ‘/api/items.json’ do
content_type :json
JSON.unparse(Items.all.map{|e|e.values})
end

Helpers

helpersブロックでメソッドを定義するとイベント内やテンプレートで使えます


helpers do
def bar(name)
“#{name}bar”
end
end
get ‘/:name’ do
bar(params[:name])
end

Rails的なpartialを定義


helpers do
def partial(page, options={})
erb page, options.merge!(:layout => false)
end
end

escape_html等のaliasを定義しとくと便利


helpers do
include Rack::Urils
alias_method :h, :escape_html
alias_method :u, :escape
end

Rack Middleware

useメソッドで指定しなさい


use Rack::Lint
get ‘/’ do
“hello”
end

Sinatra自体がいくつか読み込んでるので、重複するかもしれません。
Loggerとか。1リクエストでログが複数件でてビックリしました。

Error Handling

not_found
定義されてないURLにアクセスがあった場合に動作


not_found do
“Not found”
end

しかし、デフォルトのメッセージがセンス良すぎなので、production時にのみ定義したい。

error
例外が投げられたら動作


error do
‘error – ’ + request.env[’sinatra.error’].name
end
error MyCustomError do
‘So what happened was…’ + request.env[‘sinatra.error’].message
end

これもセンス良すぎなので次の方法でproduction時のみ動作にしましょう
configureメソッドをつかいます


configure :production do
not_found do
“Not found”
end
error do
“Error”
end
end

Configuration

configureブロックの中で変数を使う場合はsetをつかいましょう


configure :development do
set :dbname, ‘devdb’
end
configure :production do
set :dbname, ‘productiondb’
end
get ‘/whatdb’ do
’We are using the database named ’ + options.dbname
end

Deploy

個人的にはpassengerが良い
アプリケーションのrootディレクトリにtmp,publicディレクトリを作りconfig.ruを書く


#config.ru
require ‘app’
run Sinatra::Application

最新バージョンのrack(1.0)やpassennger(2.0.3)を使ったときのバグが公式に書いてありますので参照下さい。

参考

http://www.sinatrarb.com/
http://www.sinatrarb.com/book.html
http://www.sinatrarb.com/faq.html
http://www.sinatrarb.com/testing.html
http://www.sinatrarb.com/extensions.html

おしまい