昨日の記事『Ubuntu 10.04 で JRuby on Rails on GAE を始めるまでの作業ログ』では、Rails 2.3.5 で GAE プロジェクトを作りましたが、Rails 2.3.8 でも作れるようになっていました !

で、書かれていた通りやってみたところ、あっさり動きました。

作業上の変更点は以下のような感じだとおもいます。

  • Gemfile を手書きで書き足さなくてよくなった
  • ails238_appengine.rb に tiny_ds オプションはあるものの、動かない ?

というわけで、昨日書いた記事は、書いた時点で既に陳腐化してということですね …

, , ,

注意

この記事は既に情報が古くなっています。
2010 年 7 月 26 日現在での最新の情報は以下を参照してください。

この記事では、GAE (Google App Engine) 上で Ruby on Rails を動かすまでに必要な作業を紹介します。

既に GAE を利用している人であればご存知かと思いますが、GAE では Java か Python しか動かすことができないので、通常は Ruby を動かすことはできません。しかし、Java が動くということは、JRuby は動くので、その中で Rails を動かしてみよう、というものです。

この記事は、ほとんどが @urekat さんによる記事のトレースです。ただし、現在は、@urekat さんの記事そのままでは動かない部分もあるので、そこも吸収しながら紹介していきます。

@urekat さんの記事が書かれたのが 2010 年 2 月 20 日で、半年も経たずにインストール作業が変わってしまっているので、この記事も数ヶ月後には役に立たなくなっているかもしれません。以下はすべて、2010 年 7 月 25 日現在の情報である、ということにご注意ください。

今回は、Ruby のインストールから始めます。

Ruby, Rubygems, Java のインストール

Ruby は MRI (Matz’ Ruby Implementation) の 1.8.7 を用います。ここでは JRuby でないことにご注意ください。

Rubygems というのは、Ruby 用のパッケージ管理ソフトです。

Java は 1.6 を用います。

sudo apt-get install ruby rubygems openjdk-6-jdk

正常にインストールされれば、以下の用にバージョンの確認ができるはずです。

$ ruby -v
ruby 1.8.7 (2010-01-10 patchlevel 249) [i486-linux]
$ gem -v
1.3.5
$ java -version
java version "1.6.0_18"
OpenJDK Runtime Environment (IcedTea6 1.8) (6b18-1.8-0ubuntu1)
OpenJDK Client VM (build 14.0-b16, mixed mode, sharing)

Rails のインストール

先ほどインストールした Rubygems でインストールできます。

$ sudo gem install rails --version 2.3.5 --no-ri --no-rdoc
Successfully installed rake-0.8.7
Successfully installed activesupport-2.3.5
Successfully installed activerecord-2.3.5
Successfully installed rack-1.0.1
Successfully installed actionpack-2.3.5
Successfully installed actionmailer-2.3.5
Successfully installed activeresource-2.3.5
Successfully installed rails-2.3.5
8 gems installed

現在、Rails は 2.3.8 が最新ですが、rails_appengine パッケージが 2.3.5 を必要賭しているようなので、2.3.5 を指定しています。

–no-ri –no-rdoc オプションは、ドキュメントのダウンロードをスキップするものです。ドキュメントが必要であれば、これらのオプションは外して構いません。

google-appengine パッケージのインストール

ここでは、先ほどインストールした Rubygems でインストールを行います。

$ sudo gem install google-appengine --no-ri --no-rdoc
Successfully installed jruby-jars-1.5.1
Successfully installed appengine-rack-0.0.11
Successfully installed appengine-apis-0.0.18
Successfully installed appengine-sdk-1.3.5
Successfully installed bundler08-0.8.5
Successfully installed rubyzip-0.9.4
Successfully installed appengine-tools-0.0.15
Successfully installed google-appengine-0.0.15
8 gems installed

これだけで GAE 関連のライブラリ・ツールが一気にインストールされます。

しかし、通常このままでは appcfg.rb や dev_appserver.rb といったツールにパスが通っていないと思うので、Rubygems の bin ディレクトリにパスを通します。好みのエディタで ~/.bashrc ファイルを開き、一番下にでも以下のような記述を追加します。

# Rubygems
export PATH=$PATH:/var/lib/gems/1.8/bin

続いて、~/.bashrc を再読み込みすれば反映されます。

source ~/.bashrc

パスが通ったか、の確認は以下のように行うことができます。

$ which appcfg.rb dev_appserver.rb
/var/lib/gems/1.8/bin/appcfg.rb
/var/lib/gems/1.8/bin/dev_appserver.rb

ここまでは @urekat さんの記事とほとんど変わりません。ここから先に、変更点を多く含みます。

プロジェクトを作成する

ここでいう「プロジェクト」とは「ひとかたまりの Rails アプリケーション」ぐらいの意味です。そのテンプレートにあたるファイル群を生成します。

プロジェクトはひとつのディレクトリ内で行うので、適当にディレクトリを作成し、その中に移動します。

$ mkdir test_app
$ cd test_app

この中で、先ほどインストールし、パスを通した appcfg.rb コマンドを使います。最後の引数の . (ドット) に注意してください。

$ appcfg.rb generate_app .
=> Generating gemfile
=> Bundling gems
Calculating dependencies...
Updating source: http://gems.rubyforge.org
Downloading appengine-rack-0.0.11.pre.gem
Caching: jruby-jars-1.5.1.gem
Caching: jruby-rack-1.0.1.gem
Caching: rack-1.2.1.gem
Installing jruby-jars (1.5.1)
Installing rack (1.2.1)
Installing jruby-rack (1.0.1)
Installing appengine-rack (0.0.11.pre)
Done.
=> Packaging gems
=> Installing jruby-core-1.5.1.jar
=> Installing jruby-stdlib-1.5.1.jar
=> Installing jruby-rack-1.0.1.jar
=> Installing appengine-rack.jar
=> Generating rackup
=> Generating app.yaml

これで、GAE 上で JRuby アプリケーションを動かすためのテンプレートが生成されました。

私自身は試していませんが、例えば Sinatra を GAE 上で動かす、というときも、ここまでは同じ作業が必要になると思います。

次に、Rails のファイル群を生成します。途中「robots.txt を上書きしてもいいですか ?」と聞かれますが、Yes で問題ありません。

$ wget http://appengine-jruby.googlecode.com/hg/demos/rails2/rails2_appengine.rb
$ ruby rails2_appengine.rb
=> Bundling gems
Calculating dependencies...
Updating source: http://gems.rubyforge.org
Caching: actionmailer-2.3.5.gem
Caching: actionpack-2.3.5.gem
Caching: activerecord-2.3.5.gem
Caching: activeresource-2.3.5.gem
Caching: activesupport-2.3.5.gem
Downloading addressable-2.1.2.gem
Caching: appengine-apis-0.0.18.gem
Caching: appengine-rack-0.0.11.gem
Downloading dm-appengine-0.0.9.gem
Downloading dm-ar-finders-0.10.2.gem
Downloading dm-core-0.10.2.gem
Downloading dm-timestamps-0.10.2.gem
Downloading dm-validations-0.10.2.gem
Downloading extlib-0.9.15.gem
Caching: rack-1.0.1.gem
Caching: rails-2.3.5.gem
Downloading rails_appengine-0.0.4.gem
Downloading rails_dm_datastore-0.2.9.gem
Caching: rake-0.8.7.gem
Installing activesupport (2.3.5)
Installing extlib (0.9.15)
Installing rails_appengine (0.0.4)
Installing rack (1.0.1)
Installing actionpack (2.3.5)
Installing actionmailer (2.3.5)
Installing rake (0.8.7)
Installing addressable (2.1.2)
Installing dm-core (0.10.2)
Installing dm-timestamps (0.10.2)
Installing dm-validations (0.10.2)
Installing dm-appengine (0.0.9)
Installing appengine-rack (0.0.11)
Installing appengine-apis (0.0.18)
Installing dm-ar-finders (0.10.2)
Installing activerecord (2.3.5)
Installing rails_dm_datastore (0.2.9)
Installing activeresource (2.3.5)
Installing rails (2.3.5)
Deleting gem: rack (1.2.1)
Deleting gem: appengine-rack (0.0.11.pre)
Done.
=> Packaging gems
=> Installing appengine-api-labs-1.3.5.jar
=> Installing appengine-api-1.0-sdk-1.3.5.jar
=> Installing jruby-core-1.5.1.jar
=> Installing jruby-stdlib-1.5.1.jar
=> Installing jruby-rack-1.0.1.jar
=> Installing appengine-rack.jar
      exists
      create  app/controllers
      create  app/helpers
      create  app/models
      create  app/views/layouts
      create  config/environments
      create  config/initializers
      create  config/locales
      create  db
      create  doc
      create  lib
      create  lib/tasks
      create  log
      create  public/images
      create  public/javascripts
      create  public/stylesheets
      create  script/performance
      create  test/fixtures
      create  test/functional
      create  test/integration
      create  test/performance
      create  test/unit
      create  vendor
      create  vendor/plugins
      create  tmp/sessions
      create  tmp/sockets
      create  tmp/cache
      create  tmp/pids
      create  Rakefile
      create  README
      create  app/controllers/application_controller.rb
      create  app/helpers/application_helper.rb
      create  config/database.yml
      create  config/routes.rb
      create  config/locales/en.yml
      create  db/seeds.rb
      create  config/initializers/backtrace_silencers.rb
      create  config/initializers/inflections.rb
      create  config/initializers/mime_types.rb
      create  config/initializers/new_rails_defaults.rb
      create  config/initializers/session_store.rb
      create  config/environment.rb
      create  config/boot.rb
      create  config/environments/production.rb
      create  config/environments/development.rb
      create  config/environments/test.rb
      create  script/about
      create  script/console
      create  script/dbconsole
      create  script/destroy
      create  script/generate
      create  script/runner
      create  script/server
      create  script/plugin
      create  script/performance/benchmarker
      create  script/performance/profiler
      create  test/test_helper.rb
      create  test/performance/browsing_test.rb
      create  public/404.html
      create  public/422.html
      create  public/500.html
      create  public/index.html
   identical  public/favicon.ico
overwrite public/robots.txt? (enter "h" for help) [Ynaqdh] y
       force  public/robots.txt
      create  public/images/rails.png
      create  public/javascripts/prototype.js
      create  public/javascripts/effects.js
      create  public/javascripts/dragdrop.js
      create  public/javascripts/controls.js
      create  public/javascripts/application.js
      create  doc/README_FOR_APP
      create  log/server.log
      create  log/production.log
      create  log/development.log
      create  log/test.log
+ ./LICENSE
+ ./README
+ ./Rakefile
+ ./init.rb
+ ./lib/active_record/connection_adapters/nulldb_adapter.rb
+ ./lib/nulldb_rspec.rb
+ ./spec/nulldb_spec.rb
+ ./tasks/database.rake
##
## Now type './script/server.sh'
##

最後に、Gemfile というファイルに以下の記述を追加します。

gem 'appengine-rack', '0.0.10.pre'
gem 'jruby-openssl'
gem 'jruby-jars'

appengine-rack パッケージは、現在 0.0.11 が最新のようですが、どうもそれだと動かないようなので、0.0.10.pre を指定しています。

開発サーバーを起動する

以上が問題なく完了すれば、開発サーバーを起動して、動作確認してみましょう。

$ dev_appserver.rb .
=> Bundling gems
Calculating dependencies...
Updating source: http://gems.rubyforge.org
Downloading appengine-rack-0.0.10.pre.gem
Downloading jruby-openssl-0.7.gem
Installing jruby-openssl (0.7)
Installing appengine-rack (0.0.10.pre)
Deleting gem: appengine-rack (0.0.11)
Done.
=> Packaging gems
=> Installing appengine-rack.jar
=> Installing appengine-api-labs-1.3.5.jar
=> Installing appengine-api-1.0-sdk-1.3.5.jar
=> Installing jopenssl.jar
=> Installing bcmail-jdk15-144.jar
=> Installing bcprov-jdk15-144.jar
=> Installing jruby-core-1.5.1.jar
=> Installing jruby-stdlib-1.5.1.jar
=> Installing jruby-rack-1.0.1.jar
=> Booting DevAppServer
=> Press Ctrl-C to shutdown server
# 中略
情報: The server is running at http://localhost:8080/

初回は上記の用に、必要な Rubygems を jar ファイルとしてインストールする動作が伴うので時間がかかりますが、それ以降は普通にサーバーが起動するのみです。

http://localhost:8080/ にアクセスすれば、Rails のデフォルト画面が表示されているはずです。

「About your application’s environment」というテキストをクリックすると、以下のように表示されるはずです。

Ruby version	1.8.7 (java)
RubyGems	disabled
Rack version	1.1
Rails version	2.3.5
Action Pack version	2.3.5
Active Support version	2.3.5
DataMapper version	0.10.2
Environment	development
JRuby Runtime version	1.5.1
JRuby-Rack version	1.0.1
AppEngine SDK version	1.3.5
AppEngine APIs version	0.0.18
Auth domain	gmail.com
Application id:version	new-app:1

ここまでで、Ubuntu 10.04 のローカル環境において、GAE 開発サーバー上での JRuby on Rails の準備は終わりです。

その後どうするか

このあとは、自分なりのアプリケーションを開発したり、それを GAE 本番環境にデプロイしたりとしていくわけですが、それらについては @urekat さんの記事のままで問題ないようなので、ここでの説明は省きます。

これ以降については私自身も知らない部分が多いので、自分でアプリを作っていきながら、紹介していければと思います。

JRuby on Rails に興味を持った方は、日本 JRuby ユーザ会のイベントに参加してみましょう ! 次回 2010 年 8 月 6 日のイベントでは、@urekat さんの GAE についてのプレゼンも聞けます。

関連ページ

, , ,

Google App Engine (以下 GAE) 上で Amazon の Product Advertising API を扱うべく、Python の XML ライブラリについて調べていました。どうも Pythonista の間では lxml というのがメジャーらしいので、さっそく組み込んでみたのですが、どうも動かない

調べて見たところ、GAE 上では、セキュリティの関係上、C 拡張による Python ライブラリは動かないとのことで、lxml は使えないようです。

代替ライブラリを探す

C 拡張がダメということは、つまり Pure Python なライブラリなら OK、という解釈でいいのでしょうか。探してみたところ、ちょうど先日購入した [エラー: isbn:4873112761:n というアイテムは見つかりませんでした] の p.479 に「XML 文書を Python のオブジェクトツリーに変換」というレシピが載っていました。

写経、そして修正

さっそく写経してみたのですが、動かない。しばらく調べた結果、誤植によるものと思われるバグを発見。その他いくつかの修正を加えたものを GitHub に公開しました。

主な変更点は以下の通りです。

  • Xml2Obj.EndElement が上手く動かないのを修正
  • UTF-8 に対応
  • ファイルからではなく、文字列を XML として読み込むよう変更
  • __getattr__ メソッドにより、Element.getElements() のショートカットを作成 (詳細は後述)

ただし、あくまでも習作であり、エラー処理等もかなり甘いので、実用的とは言えません。
その代わり、ちょっと遊ぶ程度にはちょうどいい手軽さかも。

コード

テストコード

__getattr__ による Element.getElements() へのショートカットについて

__getattr__ というのは、インスタンスに存在しないプロパティを呼び出そうとしたときに呼び出されるもので、PHP でいうと、マジックメソッドの __get にあたるものと言えるでしょう。

これにより、以下のようなショートカットを実現しています。意味はどちらも同じです。

終わりに

もともと GAE に組み込むことを目的として上記ライブラリを修正したわけですが、実はまだ組み込めてません・・・。ただ、expat を GAE に組み込んでいる例はネット上に転がっているので、まぁこれもいけるのではないかと。真相はまた今度。

関連リンク

, , ,