はじめに
第7回 はRails以外のWebフレームワークの簡単な紹介と、SinatraでHello Worldアプリケーションを動かすところまでを解説しました。今回はSinatraで実際のアプリケーションを作り、SequelとHamlという2つのライブラリを紹介します。
Sinatraの特徴は、CGIスクリプトのようにファイル一つからアプリケーションが書ける気軽さです。CGIスクリプトといえば、代表的なものは何と言っても掲示板(BBS)です。そこで、今回はSinatraで掲示板アプリを作ってみました。ソースコードが少し長めなので、github にて全文を公開しています。適宜参照しながら読み進めて下さい。ファイル構成は以下のようになっています。
start.rb
アプリケーションの本体。
model/comment.rb
掲示板の書き込みを表すモデルの定義。
view/index.haml
トップページのHTMLの定義。
view/layout.haml
HTMLのレイアウト定義。
view/style.sass
スタイルシートの定義。
動作例は以下のようになります。
図1 今回制作する、Sinatraを利用した掲示板アプリ
SinatraのMVC
実際にアプリケーションを書くためには、データを保存したり、HTMLを出力したりする機能が必要です。Ruby on Rails(以下Rails)ではモデルのためのライブラリとしてActiveRecordが、ビューのためのライブラリとしてerbが(標準では)使われます。ではSinatraではどうなのでしょうか。
結論からいうと、モデル部分に関してはSinatraでのサポートは特にありません。そのため、ActiveRecord 、DataMapper 、Sequel といったRuby用のO/Rマッピングライブラリを一つ選んで使うことになります。
ビュー部分に関しては、Railsでおなじみのerb 、HTMLをインデントで表現するHaml 、HTMLをRubyのメソッドで表現するBuilder が標準でサポートされています。
今回は紹介も兼ねて、モデル部分にSequelを、ビュー部分にHamlを使ってみることにします。
Sequel
Sequel はRubyのコードでSQLを書くことを目指したライブラリで、データベースのきめ細かい操作を得意とします。APIは比較的シンプルで、ActiveRecordのような「モデルオブジェクト」の定義さえも必須ではありません(この場合の検索結果はハッシュで受け取ります) 。
一方、利便性のために、Sequel::Modelによるモデル定義や、has_manyなどのアソシエーション、スキーマのマイグレーションなどの機能も提供されています。今回の掲示板アプリケーションから、Sequelでモデルオブジェクトを定義している部分を見てみましょう。
リスト1 Sequelによるモデル定義の例(model/comment.rb)
Sequel.connect("sqlite://comments.db")
class Comments < Sequel::Model
unless table_exists?
set_schema do
primary_key :id
string :name
string :title
text :message
timestamp :posted_date
end
create_table
end
# (略)
end
最初の行でSQLiteのデータベースに接続しています。以降で定義しているCommentsクラスはこのデータベース内のテーブルに関連づけられます。アプリケーションを最初に起動したときはテーブルが存在しないため、set_schemaでスキーマを定義し、create_tableでテーブルを作成しています。
実際にデータを取得する部分は以下のようになります。「 ORDER BY」や「DESC」のようなSQLのキーワードを、そのままRubyの世界に写したような書き方がSequelの特徴です。
リスト2 Sequelによるクエリの例(start.rb)
@comments = Comments.order_by(:posted_date.desc)
Haml
今回紹介するもう一つのライブラリHaml は、HTMLをYAML のように簡潔に記述するマークアップ言語です。日本Hamlの会 というユーザグループが存在するなど、日本でも愛好者を増やし始めています。
実際の例を見てみましょう。以下のコードはHamlでHTMLのレイアウトを表現したものです。
リスト3 HamlによるHTML表現の例(views/layout.haml)
!!! XML
!!! Strict
%html
%head
%title SinatBBS
%meta{:"http-equiv"=>"Content-Type", :content=>"text/html", :charset=>"utf-8"}
%link{:rel=>"stylesheet", :type=>"text/css", :href=>"/style.css"}
%body
%h1 SinatBBS
!= yield
<html>や<body>といったタグの階層構造がインデントで表されます。「 閉じタグ」が存在しない分、見た目が簡潔になっています。
もう一つ、掲示板の投稿を表示する箇所も見てみましょう。
リスト5 HamlによるHTML表現の例(views/index.haml)
- @comments.each do |comment|
.comment
%h2= h comment.title
.info
%span.name== by #{h comment.name}
%span.date== (#{h comment.date})
.message
= comment.formatted_message
タグ名は「%h2」のように%を使って指定するほか、「 %div.info」のようにclass名を同時に指定することもできます。タグ名がdivのときは省略可能なので、単に「.info」と書いても同じです。
タグ名のあとに「=」を書くとerbの「」のように値を埋め込むことができます。「 ==」は「=」と似ていますが、Rubyの「#{}」を使うことができるため、値と文字列が混在しているときに便利です。
eachメソッドで繰り返しを行う場合、erbでは「」を使いますが、Hamlでは行頭に「-」を付けます。ブロックの終わりはインデントで表現するため、「 end」を書く必要はありません。
Sass
Hamlには、SassというCSSを生成するためのライブラリも同梱されています。Haml同様、インデントを利用するため見た目が簡潔になるほか、「 div.comment内のh2タグ」のような階層構造を分かりやすく表現することができます。
また、変数を使って複数箇所で使われる値を定義したり、計算式を使って相対的な値の指定を行ったりと、複雑なCSSにも対応できる機能を備えています。CSS生成用のライブラリとして使っても役に立つでしょう。
今回のアプリケーションではview/style.sass にSassによるCSSの定義があります。
アプリケーション本体
今回はSequelがモデル部分を、Hamlがビュー部分を担当しているので、リクエストを受け取ってHTMLを生成するコントローラ部分がSinatraの役割になります。今回はRESTの作法に従い、GETメソッドでトップページを取得し、PUTメソッドでコメントを投稿するようにしました。
リスト6 Sinatraによるコントローラ部分(start.rb)
get '/' do
@comments = Comments.order_by(:posted_date.desc)
haml :index
end
put '/comment' do
Comments.create({
:name => request[:name],
:title => request[:title],
:message => request[:message],
:posted_date => Time.now,
})
redirect '/'
end
PUTメソッドはサーバによってはサポートされないため、Railsと同様、「 _method=PUT」というパラメータが指定されたときにputメソッドで登録したハンドラが呼ばれることになっています。
Sinatra、その先に
今回は「モダンなCGI」としてSinatraを利用してみましたが、Sinatra: The Book の目次を見ると、「 Memcachedベースのセッション」や「Passenger(mod_rails)を利用したデプロイ」など、大規模サイトでの使用も視野に入れられていることが分かります。
確かに、コードの規模は小さいが大量にアクセスされるアプリケーションというものは存在します。Railsでは捌ききれない、特にアクセスの多い部分だけをSinatraで実装するというような使い分けも考えられそうです。
その他、Google App Engine上で動作した という報告もあり、今後もSinatraには要注目です。詳しい情報は公式サイト のほか、githubのリポジトリ検索を使う ことで、Sinatraで書かれたアプリケーションの実例を探すことができます。
まとめ
今回はSinatraとSequel、Hamlを組み合わせてアプリケーションを作成する例を紹介しました。
次回は、また毛色の違うフレームワーク「Ramaze」をご紹介する予定です。お楽しみに!