December 18, 2009

GAE で Sinatra を使って “foo” を表示する最速の方法

appengine_lowres

あなたは急に、 Google App Engine で Sinatra を使って “foo” を表示したくなりました。

以下は、現時点で僕が知ってるその最速の方法です。
参考にしてください。
ちなみに環境は Mac OSX です。

google-appengine というライブラリを gem でインストールします。

% gem install google-appengine

プロジェクトのディレクトリを作成します。

% mkdir foo
% cd foo

config.ru というファイルを作成します。
以下を記述します。

require 'appengine-rack'
AppEngine::Rack.configure_app(
  :application => "application_id",
  :version => 1
)
require 'foo.rb'
run Sinatra::Application

Gemfile というファイルを作成します。

# Critical default settings:
disable_system_gems
disable_rubygems
bundle_path ".gems/bundler_gems"
# List gems to bundle here:
gem "appengine-rack"
gem "sinatra"

foo.rb というファイルを作成します。

require 'sinatra'

get '/' do
  'foo'
end

試しにローカルで起動してみます。

% dev_appserver.rb .

(僕の環境だと一回目はなぜか起動に失敗します)

そしていよいよデプロイです。

% appcfg.rb update .

デプロイが完了したら http://<application_id>.appspot.com/ にアクセスしてみましょう。
立ち上がりはお世辞にも早いとは言えませんが、そのうち foo が表示されるはずです。

Picture 13

enjoy foo!

See also: http://code.google.com/p/appengine-jruby/

December 15, 2009

sinatra_debug_console

Description

http://github.com/jugyo/sinatra_debug_console

Debug console for sinatra

Debug console for sinatra

Installation

gem install sinatra_debug_console

Usage

require 'sinatra_debug_console'
Sinatra::DebugConsole.config(USERNAME, PASSWORD)

Example

# % ruby app.rb
# see http://localhost:4567/debug_console

require 'sinatra'
require 'sinatra_debug_console'
Sinatra::DebugConsole.config('admin', 'password')
April 20, 2009

Sinatra が Google App Engine で動くまで

(注: Google App Engine を GAE と略すことがあります。)

Sinatra を Google App Engine で動かしてみました。

Github にすぐに動かせるものを置いておいたので、手っ取り早く試したい人はここからソースを取ってきて動かしてみるといいと思います。
appengine-java-sdk は別途必要です。

http://github.com/jugyo/sinatra_on_gae/tree/master

詳細は同梱されている README を参照してくだい。

以下は、ちゃんと手順を追って試してみたい人向けの解説です。

SDK のダウンロード

SDK をマシンに入れておく必要があります。
以下から appengine-java-sdk-1.2.0.zip というのをダウンロードして適当な場所に解凍してください。

http://code.google.com/appengine/downloads.html

PATH の設定

SDK の bin ディレクトリを PATH に追加しておきます。
コマンドを実行するときにフルパスを指定するのが面倒なので。

例:

export PATH=$PATH:~/src/jruby/appengine-java-sdk-1.2.0/bin

アプリケーションのフォルダを作成

フォルダをいくつか作ります。

cd sinatra_on_gae
mkdir WEB-INF
mkdir WEB-INF/gems WEB-INF/lib

ライブラリのインストール

必要なライブラリを gem でインストールします。
その際、-i オプションでディレクトリを指定します。
さらに、rdoc や ri はいらないので –no-rdoc –no-ri オプションも付けておきます。

gem install -i WEB-INF/gems sinatra --no-rdoc --no-ri

以下のファイルは不要なので削除しておきます。

rm -rf WEB-INF/gems/bin WEB-INF/gems/cache/*

jar ファイルの用意

WEB-INF/lib に以下の jar ファイルを置きます。

appengine-api-1.0-sdk-1.2.0.jar
jruby-core.jar
ruby-stdlib.jar
jruby-rack-0.9.4.jar

appengine-api-1.0-sdk-1.2.0.jar は SDK に含まれているライブラリで、 jruby-core.jar と ruby-stdlib.jar は、Github から取ってきた JRuby をビルドして必要なものだけ抜き出したものです。
jruby-rack-0.9.4.jar も Github から取ってきてビルドしました。

Sinatra アプリケーションを作成

Sinatra 上で動かすアプリケーションを作ります。

WEB-INF/app.rb

require 'rubygems'
require 'sinatra'

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

やっぱり Sinatra はシンプルでいいですね〜。

appengine-web.xml の作成

GAE アプリケーションとしての設定を appengine-web.xml というファイルに書きます。

WEB-INF/appengine-web.xml

<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
    <application>sinatra_on_gae</application>
    <version>1</version>
    <static-files />
    <resource-files />
    <sessions-enabled>false</sessions-enabled>
    <system-properties>
      <property name="jruby.management.enabled" value="false" />
      <property name="os.arch" value="" />
      <property name="jruby.compile.mode" value="JIT"/> <!-- JIT|FORCE|OFF -->
      <property name="jruby.compile.fastest" value="true"/>
      <property name="jruby.compile.frameless" value="true"/>
      <property name="jruby.compile.positionless" value="true"/>
      <property name="jruby.compile.threadless" value="false"/>
      <property name="jruby.compile.fastops" value="false"/>
      <property name="jruby.compile.fastcase" value="false"/>
      <property name="jruby.compile.chainsize" value="500"/>
      <property name="jruby.compile.lazyHandles" value="false"/>
      <property name="jruby.compile.peephole" value="true"/>
   </system-properties>
</appengine-web-app>

web.xml の作成

Web アプリケーションの設定を web.xml に記述します。

WEB-INF/web.xml

<!DOCTYPE web-app PUBLIC
  "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
  "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>

  <context-param>
    <param-name>public.root</param-name>
    <param-value>/</param-value>
  </context-param>

  <context-param>
    <param-name>rackup</param-name>
    <param-value>require 'rubygems'
require 'sinatra'

root_dir = File.dirname(__FILE__)

#set :environment, :production
set :environment, :development
set :root,        root_dir
set :app_file,    File.join(root_dir, 'app.rb')
disable :run

require 'app'

run Sinatra::Application
</param-value>
  </context-param>

  <context-param>
    <param-name>jruby.min.runtimes</param-name>
    <param-value>1</param-value>
  </context-param>

  <context-param>
    <param-name>jruby.max.runtimes</param-name>
    <param-value>1</param-value>
  </context-param>

  <context-param>
    <param-name>jruby.init.serial</param-name>
    <param-value>true</param-value>
  </context-param>

  <filter>
    <filter-name>RackFilter</filter-name>
    <filter-class>org.jruby.rack.RackFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>RackFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <listener>
    <listener-class>org.jruby.rack.RackServletContextListener</listener-class>
  </listener>

</web-app>

sinatra のソースをちょっとだけ修正する必要があります。
WEB-INF/gems/gems/sinatra-0.9.1.1/lib/sinatra.rb の8行目です

use_in_file_templates!

#use_in_file_templates!

use_in_file_templates! というのはおそらく、ファイルの中にテンプレートを書いておける機能にまつわるメソッドだと思います。
ま、いらないと思います。

GAE のアプリとして起動する

さて、以上でアプリケーションを動かす準備が整いました。
以下のようにして起動するとこができます。

dev_appserver.sh .

ちなみに、起動の際には WEB-INF ディレクトリが置かれているディレクトリを指定する必要があります。

普通の Ruby で起動する

普通の Ruby でも当然動きます。

GEM_HOME=WEB-INF/gems ruby ./WEB-INF/app.rb

デプロイ

appengine-web.xml の application と version を適切に設定した上で以下を実行するとデプロイできます。

appcfg.sh update .

当然、Google App Engine のアカウントを持っていてかつ Java が使えるようなっている必要があります。

デモ

以下で実際に動かしてます(一週間くらいは動かしておくつもりです。Hello World!! しか出ませんけどね!)。

http://jugyo-test.appspot.com/

参考:
http://blog.bigcurl.de/2009/04/running-sinatra-apps-on-google.html

April 19, 2009

Hamlr が Google App Engine で動くまで

あとで書く。

関連:
Sinatra が Google App Engine で動くまで

December 10, 2008

Sinatra で Partial を

ヘルパーメソッドの定義

以下のヘルパーメソッドを追加します。

helpers do
  def partial(renderer, template, options = {})
    options = options.merge({:layout => false})
    template = "_#{template.to_s}".to_sym
    m = method(renderer)
    m.call(template, options)
  end

  def partial_haml(template, options = {})
    partial(:haml, template, options = {})
  end

  def partial_erb(template, options)
    partial(:erb, template, options)
  end
end

Sinatra では、ヘルパーメソッドは「helpers do … end」の中に定義します。
参考: http://sinatra.rubyforge.org/book.html#helpers

使い方

ビュー側で、

= partial :haml, :test, :locals => { :foo => 'bar' }

もしくは、

= partial_haml :test, :locals => { :foo => 'bar' }

のようにして呼び出します。

partial 用のテンプレートは、ファイル名の頭にアンダースコア「_」が付いている必要があります。
例えば上の例だと「_test.haml」というファイルが読み込まれます。

ERB の場合は、

= partial :erb, :test, :locals => { :foo => 'bar' }

もしくは、

= partial_erb :test, :locals => { :foo => 'bar' }

のようにし、テンプレートファイルは「_test.erb」のような名前にします。

微妙なところ

「:locals => {:foo => bar}」として変数を partial 用のテンプレートに引き渡していますが、実行コンテキストが呼び出し元と同じなのでインスタンス変数が参照できてしまいます。
これってどうなんでしょう?
ていうか、Raisl の partial ってどうなってたんでしたっけ?