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/

November 6, 2009

Google App Engine (Python) でテストを書くには

Google App Engine (Python) でテストを書くにはどうしたらいいんだろう、と思ってちょろっと調べた。

Google で検索してまずここを見た。
http://blog.appenginefan.com/2008/06/unit-tests-for-google-app-engine-apps.html

ここも見た。
http://coreblog.org/ats/3-tips-to-perform-test-driven-development-with-google-app-engine

nose-gae

nose-gae
http://code.google.com/p/nose-gae/
使い方
http://farmdev.com/projects/nosegae/

python に nose というテスティングフレームワークがあるっぽくて、それを GAE アプリで使えるようにしているもののよう。
簡単に使えそうな印象。

nose
http://somethingaboutorange.com/mrl/projects/nose/0.11.1/

webtest という WSGI アプリをテストするためのライブラリと組み合わせて使うとよさそう。

webtest
http://pypi.python.org/pypi/WebTest/

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 19, 2008

Google App Engine で Google GData API を使う (2)

前回の続きです。

Picasa での認証

えーっと、やりたいことは Picasa から private な画像の情報を取ってくることです。
そのためには Picasa 側で認証処理を通す必要があります。
具体的に何をやるかというと、private な情報にアクセスするための「トークン」を Picasa に発行してもらいます。
そのためには実際ちょっとややこしい手順を踏む必要があります。

扱うトークンには「AuthSub Token」と「AuthSub Session Token」の2種類があります。
「AuthSub Token」は一度しか使えないトークンです。
トークンが一度しか使えないとアプリケーション的にはちょっと不便なので、何度でも使えるトークンが欲しいところです。
そこで「AuthSub Session Token」です。
「AuthSub Session Token」を使えば何度でもデータを取ってこれます。

処理の流れとしては、まず「AuthSub Token」を Picasa に発行してもらい、それを使って「AuthSub Session Token」を取得する、というふうになります。
わかりやすいように絵にしてみました。

authsub_token_1.png
まず「AuthSub Token」を発行してもらいます。
Picasa 側でアクセス許可の操作を行った後、URL にトークンを含んだ状態でリダイレクトされてアプリ側に帰ってきます。

authsub_token_1.1.png
「AuthSub Token」をゲットしました。

authsub_token_2.png
取得した「AuthSub Token」を使って今度は「AuthSub Session Token」を発行してもらいます。

authsub_token_2.1.png
「AuthSub Session Token」をゲットしました。
このトークンはデータベースに保存するなどして大事に取っておきます。

authsub_token_3.png
「AuthSub Session Token」を使えば private な画像の情報も取得できます。

意外と面倒くさいですが、理解してしまえば簡単です。
あとは API を使ってどんなアプリケーションを作るか考えるだけです。

サンプルコード

以下にサンプルコードを置いたので、よかったら参考にしてください。

http://github.com/jugyo/using-picasa-web-albums-data-api

Google App Engine で動くように実装されています。

関連記事

Google App Engine で Google GData API を使う (1)

December 15, 2008

Google App Engine で Google GData API を使う (1)

GAE Hack-a-thon に行ってきました

GAE Hack-a-thon というのに行ってきました。
Google App Engine で何か作るハッカソンです。
渋谷にあるグーグルのオフィスで開催されました。
昼食のお弁当がおいしかったです。
ありがとうございました。

さて、僕はマッシュアップなアプリを Google App Engine を使って作ることに挑戦しました(マッシュアップっていう単語、最近あまり聞かなくなりましたね。)。
4人のチームを組んで取り組みました。
みんなでドキュメントを探したりサンプルコードを解読したりしながら作業したんですけど、なかなか楽しかったです。
チームを組んで何かを作るって、仕事以外ではあんまりやらないので新鮮でした。

gdata-python-client

具体的に何をやったかというと、Google Data API というものを使って Picasa から画像の情報を取ってくるプログラムを作りました。

gdata-python-client という便利なライブラリがあったのでこれを活用しました。
python で Google Data API を扱うためのライブラリです。

以下のページからダウンロードできます。
gdata-python-client

Picasa Web Albums Data API

Picasa からデータを取ってくるには、Google Data API に含まれる Picasa Web Albums Data API という API を使います。
gdata-python-client ライブラリに含まれている PhotoService クラスを使ってこの API にアクセスすることができます。
Picasa からちゃんと画像の情報が取ってこれるか以下のコードで確認してみました。

http://gist.github.com/35853

このコードを実行すると、<ユーザーID> に指定したユーザーのアルバムとそれに含まれる画像の情報が全て取得できます。

当然ながらこのプログラムでは private なアルバムのデータは取ってこれません。
private なデータを取得するためには、Picasa 側でアクセスを許可してやる必要があります。
その認証に関わる部分を Google App Engine 上で実装したんですけど、これがなかなか難しくて(というか全然理解していなくて)、一筋縄ではいきませんでした。

続く…