GAE/J+jRuby+SinatraでWebアプリ開発-インストール〜デプロイ編

前回のエントリから大分時間が経ってしまいましたが、GAE/J+jRuby+sinatraruby製Webアプリケーションを簡単に公開出来る感じなので試してみます。今回はプロジェクトの作成〜sinatraのインストール〜本番環境へのデプロイです。

プロジェクトの作成

プロジェクト名(開発時のプロジェクトディレクトリと公開後のドメインになる)を決めて以下のコマンドでプロジェクト作成します。

$ appcfg.rb generate_app {appname}

プロジェクトフォルダには以下のようなファイルとディレクトリが自動生成されます。

$ ls {appname}
-rw-r--r--  1 iskata  staff  149  5 10 01:10 Gemfile
drwxr-xr-x  6 iskata  staff  204  5 10 01:11 WEB-INF
drwxr-xr-x  3 iskata  staff  102  5 10 01:11 bin
-rw-r--r--  1 iskata  staff  219  5 10 01:11 config.ru
drwxrwxrwx  4 iskata  staff  136  5 10 01:11 public

gemのインストール

必要なgemはプロジェクト単位にインストールする必要があります。追加したいgemを自動生成された「Gemfile」というファイルの中に記述するだけでOK。デフォルトでappengine-rackはバンドルされているので、とりあえずsinatraを追加します。

## Gemfile ##
# Critical default settings:
disable_system_gems
disable_rubygems
bundle_path ".gems/bundler_gems"

# List gems to bundle here:
gem "appengine-rack"
gem "sinatra" # <<追加

実際のインストールは以下のコマンド一発で依存関係の解決も含めて全て対応してくれます。すごいラクチン。

$ appcfg.rb bundle .

*注)参考サイトでも情報が古いものだと以下のようにしてインストールしている記事がありますが、今はDeprecatedってエラーが出て動かないです。(Deprecatedだったら動いてもイイと思うのだけど・・)

appcfg.rb gem install <gemname>
Sorry, the 'appcfg.rb gem' option is deprecated.
Simply update the 'Gemfile' and run 'appcfg.rb bundle .' instead.

config.ruの設定

自動生成されたconfig.ruは生のrackを使うようになっているので、sinatraベースのアプリ本体をrequireして、run Sinatra::Applicationに書き換えます。

# 変更前
require 'appengine-rack'
AppEngine::Rack.configure_app(
    :application => "{appname}",
    :precompilation_enabled => true,
    :version => "1")
run lambda { Rack::Response.new("Hello").finish }
# 変更後
require 'appengine-rack'
AppEngine::Rack.configure_app(
    :application => "{appname}",
    :precompilation_enabled => true,
    :version => "1")
require 'iskata' #この名前はsinatraアプリのメインルーチンのファイル名と合わせる
run Sinatra::Application

sinatraアプリケーションの開発

プロジェクトのホームディレクトリに、以下のファイルとディレクトリを作成します。

iskata.rb      # sinatraアプリのメインルーチン
views/          # erb , haml , sass というテンプレートエンジンがデフォルトで使える。
models/       # ロジックは取り敢えずこの中に置くようにする
controllers/ # あまり複雑な振り分けが無かったらsinatraだけで処理してもいいかも

iskata.rbという名前でとりあえず以下のアプリを。"/"と"/world"の2つのリソースを処理できるようにしてみます。

# iskata.rb
require 'rubygems'
require 'sinatra'
# /へのリクエスト
get '/'  do
  erb :index
end
# /worldへのリクエスト
get '/world' do
  erb :world
end

テンプレートエンジンのhamlとsassはDSLで簡潔にHTMLを書けるのがメリットみたい。僕はHTMLが好きなので素直にerbを使います。layout.erbという名前で共有テンプレートを使える。views/の中身は以下のような感じ。

$ ls views/
index.erb # /のページテンプレート
world.erb # /worldのページテンプレート
layout.erb # レイアウトを決める共通テンプレート

layout.erb。<%=yield%>のところにindex.erbの処理結果が入ってきます。

< !--layout.erb-- >
<html>
<head><title>iskataのGAEアプリ</title></head>
<body>
<div id="wrapper">
  <div id="header"><img src="/images/logo.png"></div>
    <div id="content">
      Hello <%= yield %>
    </div>< !-- /content -- >
</div>< !-- /wrapper -- >
</body>
</html>

「/」はとりあえず自分の名前を呼んでもらうように、「/world」はHello, World!と返してくれるようにします

< !--index.erb-- >
Iskata!
< !--world.erb-- >
World!

Staticコンテンツの配置

画像、CSSJavaScriptなどのStaticなコンテンツはpublic/に配置します。images/、css/、scripts/とそれぞれディレクトリを作って使うことに。最初からrobots.txtfavicon.icoがあるのでそれはそのままに。

$ ls public/
favicon.ico
robots.txt
images/
css/
scripts/

開発サーバーの起動

ここまでで一通り揃ったのでローカルで確認します。GAE/Jの開発用Webサーバーをローカルに起動するにはシンプルに以下のコマンドを実行するだけでOKです。

$ dev_appserver.rb .

フォアグラウンドでlocalhost:8080でサーバーが立ち上がります。「http://localhost:8080/」にアクセスして開発した画面が見えてればOK。落としたいときはCtrl+Cで。

本番へのデプロイ

ある程度ローカルで動いたら以下のコマンドで本番のGAEへデプロイします。

$ appcfg.rb update .

http://{appname}.appspot.com/ にアクセスすると"Hello, Iskata"が表示されて、http://{appname}.appspot.com/worldなら"Hello, World"が表示されます。おおー、なんて簡単なんだ。ちょっと感動します。

まとめ

GAE/J+jRuby+sinatraの組み合わせで、公開可能なRubyのWebアプリがかなり手軽に作成できます。個人で軽く使う範囲にはほぼお金もかからないと思いますしオススメです。

次回

Twitterのリストのタイムラインを表示してみます。

補遺

  1. 現在(2010/5/14)のところGAE/J+jRubyの上で動くWAFはsinatraが現実的な選択肢のようです。Railsは起動に時間がかかりすぎてきついみたい。
  2. ただこれはGAEの現時点での制約なので、今後改善されるんじゃないかなと期待。