Ruby Freaks Lounge

第9回SinatraとSequel・Hamlで掲示板アプリを作る

はじめに

第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を利用した掲示板アプリ
図1 今回制作する、Sinatraを利用した掲示板アプリ

SinatraのMVC

実際にアプリケーションを書くためには、データを保存したり、HTMLを出力したりする機能が必要です。Ruby on Rails(以下Rails)ではモデルのためのライブラリとしてActiveRecordが、ビューのためのライブラリとしてerbが(標準では)使われます。ではSinatraではどうなのでしょうか。

結論からいうと、モデル部分に関してはSinatraでのサポートは特にありません。そのため、ActiveRecordDataMapperSequelといったRuby用のO/Rマッピングライブラリを一つ選んで使うことになります。

ビュー部分に関しては、RailsでおなじみのerbHTMLをインデントで表現するHamlHTMLを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」をご紹介する予定です。お楽しみに!

おすすめ記事

記事・ニュース一覧