(Java+Derby)* Ruby on Rails プログラミング小山博史のJavaを楽しむ(4)

教育界、技術者コミュニティでJava言語の教育と啓蒙に長年携わってきた筆者が、独自の視点からJavaの面白さを掘り下げていく。(編集部)

» 2007年02月07日 00時00分 公開
[小山博史,ガリレオ]

 Java SE 6のリリースにより、Javaプログラミングにおけるスクリプトの重要性もますます高まってきています。いうまでもありませんが、これからはWebサービスをいかに実現していけるか、ということがビジネスにおいて重要ですから、これを実装する言語として、RubyPythonPHPといったプログラミング言語に興味を持ち始めている開発者も多いのではないでしょうか?

 今回は、そんなJavaプログラマがRubyでプログラミングをするとしたら、どんな環境を用意するのがいいのだろうか、ということで調べてみました。

JRuby on Railsとは何か?

 プログラミング言語Rubyといって最初に注目するのは、なんといってもRailsでしょう。RoR(Ruby on Rails)が世の中に紹介されてから、はやるまではあっという間でした。DRY(Don't Repeat Yourself 繰り返しはやめよう)、Convention over Configuration(設定よりも規約)、といった方針で開発を進めることができる、という点が開発者から支持されたのでしょう。このような状況ですから、Rubyをさわってみたい、とJavaプログラマが考えるのも当たり前のことです。

編集部注RoR(Ruby On Rails)についての詳細を知りたい読者は、「Javaから見たRuby on Rails」をご参照願います。

 では、JavaプログラマがいまからRubyを始めるとしたら、どうするのが良いでしょうか。単にRubyを使うだけではつまらないですから、Javaと連携させたいと思うのではないでしょうか。

 検索エンジンで探すとすぐに見つかりますが、世の中にはJavaによるRubyの実装版JRubyというものがあります。JRubyは2006年7月までは、「sourceforge.net」で開発されていましたが、2006年8月からは、「codehaus.org」に移動しています。2006年9月には、JRubyのコア開発者であるCharles Oliver Nutter氏とThomas Enebo氏はSun Microsystemsに勤めることになり、開発コミュニティでは大きなニュースとなりました。

 JRubyは100%純粋なJavaプログラムなので、Javaの実行環境があれば使えます。JRubyのバージョンは0.9.2なので、力不足のように思ってしまうかもしれませんが、Railsに必要なRuby1.8.5と互換性がありますから大丈夫です。何といっても、JavaのクラスをRubyから使える、というのは魅力的です。ライセンスもCPLGPLLGPLの中から選択できます。ということで、最新版のJRubyでRailsを動かしてみることにしました。

JRuby on Railsをインストールするには?

 早速、JRubyのサイトからたどれる「Index of /jruby」へアクセスし、jruby-java5-bin-0.9.2.tar.gzをダウンロードしました。

 今回は、Fedora Core 5へSunのJDK 6をインストールした環境で実行するようにします。筆者のFedora Core 5の場合は、gijがインストールされていたので、確実にJDK6を使うように環境変数を設定しました。ここでは、/usr/java/jdkへJDK6をインストールしたとしています。

編集部注:Fedora Core 5でのgijの使い方についての詳細を知りたい読者は、「小山博史のJavaを楽しむ(2)、いろいろなJavaを使ってみよう」の「GNU系のJavaの実装」「gcj、gij、jikesの使い方」をご参照願います。

 JRubyのインストール自体は非常に簡単に終わりました。実際にコマンドを使ってバージョンを確認してみると、JRubyの最新版はRuby 1.8.5互換であることが分かりました。Railsの最新版は1.2で、Ruby 1.8.5が必要なのですが、大丈夫そうです。ここまでは特に問題ありませんでした。

$ mkdir ~/program; cd ~/program
$ wget http://dist.codehaus.org/jruby/jruby-java5-bin-0.9.2.tar.gz
$ tar xzf jruby-java5-bin-0.9.2.tar.gz
$ export JAVA_HOME=/usr/java/jdk
$ export JRUBY_HOME=~/program/jruby-0.9.2
$ export PATH=$JAVA_HOME/bin:$JRUBY_HOME/bin:$PATH
$ jruby -version
ruby 1.8.5 (0) [java]
バージョン確認

 さて、目標とするJRuby on Railsのインストールですが、普通にインストールできるようです。そこで、Railsのサイトにある説明に従って、インストールを進めました。

 インストールに当たっては、RubyのパッケージマネージャであるRubyGemsが必要だということなので、RubyGemsのサイトからrubygems-0.9.0.tgzをダウンロードして展開しました。

 実は、ここで失敗して、最初はrubygems-0.9.1.tgzをダウンロードしてしまいました。筆者の環境では、それを使うと、Railsのインストールができませんでした。ともあれ、RubyGemsのインストールはrubygems-0.9.0.tgzを展開してから、jrubyコマンドでsetup.rbを実行するだけでした。

$ tar xzf rubygems-0.9.0.tgz; cd rubygems-0.9.0
$ jruby setup.rb
Railsインストール

 RubyGemsのようなパッケージマネージャを使うと、いろいろなライブラリのインストールがとても簡単にできます。JCP(Java Community Process)を通じて仕様がコントロールされているJavaでは、あまり必要性がないかもしれませんが、やはり実装の選択肢も増えてきているので、Javaにもパッケージマネージャのようなものが欲しくなってきます。Apache Mavenがパッケージを管理する似たような機能を提供していますから、もしかしてこれが標準になっていくのかもしれません。

編集部注:JCPについての詳細を知りたい読者は、「Javaプログラマになるための定番Javaサイトの歩き方」の「これからのJava技術を知るために「JCP(Java Community Process)」」をご参照願います。

編集部注:Apache Mavenについての詳細を知りたい読者は、「Java開発支援ツールの定番」の「Maven」をご参照願います。

 RubyGemsのインストールができたので、いよいよRailsのインストールになりましたが、ここで注意が必要です。最初は、これに気が付かなくて結構時間を取られてしまいました。gemの実行をするに当たってはjrubyを明示的に指定して使う必要があるのです。

 なお、ここでは、時間を短縮するために「--no-ri」(RIドキュメントを生成しない)、「--no-rdoc」(RDocドキュメントを生成しない)としています。成功すると、railsだけでなく、rakeactivesupportといった依存関係にあるモジュールもインストールされます。ついでに、後で使うので、activerecord-jdbcもインストールしておきます。

$ jruby $JRUBY_HOME/bin/gem install rails -y --no-ri --no-rdoc
 
(略)
 
warning: JRuby does not currently support defining finalizers
Successfully installed rails-1.2.1
Successfully installed rake-0.7.1
Successfully installed activesupport-1.4.0
Successfully installed activerecord-1.15.1
Successfully installed actionpack-1.13.1
Successfully installed actionmailer-1.3.1
Successfully installed actionwebservice-1.2.1
$ jruby $JRUBY_HOME/bin/gem install activerecord-jdbc -y --no-ri --no-rdoc
 
(略)
 
Successfully installed ActiveRecord-JDBC-0.2.2
gemの実行

 ちなみに、途中に警告が出ていましたが、取りあえずインストールはできたようです。何度か試したところ、うまくいかないときもあるようです。そんなときは、rakeだけ先にインストールする(上記コマンドのrailsをrakeに変更するだけ)など、1つずつインストールすると大丈夫な場合もありますから、試してみるとよいでしょう。

 さて、実行をするときにもjrubyを使います。Railsのサイトには、「rails path/to/your/new/application」と書いてあるのですが、このとおりに実行すると、筆者の環境では、「require: command not found」などのエラーが出てしまいました。何がいけないのかと、「$JRUBY_HOME/bin/rails」コマンドの中身を見たところ、普通のRubyプログラムでしたから、明示的にjrubyコマンドを指定して実行すればいい、と気が付きました。ここでは、~/workspaceというディレクトリをあらかじめ作成しておいて、そこへsampleappアプリケーションを作成することにしました。

 railsコマンドが成功して、Railsアプリケーションが作成されてから、WEBrickサーバを実行して、http://localhost:3000/へアクセスしました。きちんと初期画面を表示できたので、後は普通にRailsを使うのと同じように開発できるのが分かりました。

$ mkdir ~/workspace
$ jruby $JRUBY_HOME/bin/rails ~/workspace/sampleapp
$ cd ~/workspace/sampleapp; jruby script/server
=> Booting WEBrick...
=> Rails application started on http://0.0.0.0:3000
=> Ctrl-C to shutdown server; call with --help for options
[2007-01-29 17:51:03] INFO  WEBrick 1.3.1
[2007-01-29 17:51:03] INFO  ruby 1.8.5 (0) [java]
[2007-01-29 17:51:03] INFO  WEBrick::HTTPServer#start: pid=5947506 port=3000
Railsの実行

JRubyでJDBC接続

 せっかくRailsを使うようになっても、データベースが使えないとあまり意味がありません。調べてみると、Railsで使っているActiveRecordモジュールでは、JDBCと連携させる方法がありました。ActiveRecord-JDBCというモジュールを使えばいいようなので、こちらもインストールして使ってみることにしました。

 データベースはせっかくなので、JDK 6に付属するDerbyを使います。「小山博史のJavaを楽しむ(3)、待望のJava SE 6 でパーシステンス」では、組み込みモードで使いましたが、ここではサーバモードで起動して、サーバクライアント方式でDBを利用することにしました。認証も付けておきたいので、設定ファイルを次のように作成してDB用にアカウントとパスワードを設定し、作成するテーブル用のSQL文も用意しておきました。

derby.connection.requireAuthentication=true

derby.authentication.provider=BUILTIN

derby.user.adminuser=sapass

設定ファイル(~/workspace/sampleapp/db/derby.properties)

create table users (

  id integer not null generated

    always as identity (start with 1, increment by 1),

  name varchar(255)

);

SQL文ファイル(~/workspace/sampleapp/db/create.sql)
$ export JAVA_HOME=/usr/java/jdk
$ export DERBY_HOME=$JAVA_HOME/db
$ cd ~/workspace/sampleapp/db
$ $DERBY_HOME/frameworks/NetworkServer/bin/startNetworkServer.ksh
Derbyをサーバモードで起動

 サーバを起動したら、別コンソールを開いて次のようにデータベースを作成して、さらにSQL文ファイルを読み込み実行してテーブルを作成しました。なお、sampledbデータベースが作成されると「~/workspace/hello/db」にsampledbディレクトリが作成されているはずです。MySQLなどをわざわざ用意しなくてもDerbyだけで準備が済むので、手間が全然掛かりません。

$ $DERBY_HOME/frameworks/NetworkServer/bin/ij.ksh
ij バージョン 10.2
ij> connect 'jdbc:derby://localhost/sampledb;create=true;user=adminuser;password=sapass';
ij> run 'create.sql';
 
(略)
 
ij> quit;
0 行が挿入/更新/削除されました
別コンソールでテーブル作成

 注意

 なお、Derbyを停止するには、次のようにコンソールからコマンドを入力します。

$ $DERBY_HOME/frameworks/NetworkServer/bin/stopNetworkServer.ksh


 最後に、Railsのデータベース設定を行いました。通常は、ymlファイルだけを編集すればよいのですが、ActiveRecord-JDBCを使うために、環境ファイルも編集が必要です。環境ファイルについては、File.joinの記述がある行の下へjdbc_adapterに関する記述を追加しました。

development:

adapter: jdbc

driver: org.apache.derby.jdbc.ClientDriver

url: jdbc:derby://localhost:1527/sampledb

username: adminuser

password: sapass

Railsのデータベース設定(~/workspace/hello/config/database.yml)

require File.join(File.dirname(__FILE__), 'boot')

require 'active_record/connection_adapters/jdbc_adapter'

Rails環境ファイル(~/workspace/hello/config/environment.rb)

 データベースとRailsの準備が整ったので、いざ、データベースドライバを含むJARファイルをCLASSPATHへ含めながら、scaffold(「足場」と訳されます)の生成を実行してみました。無事に生成ができたので、http://localhost:3000/usersへアクセスしてみると、しっかりとscaffoldで作成された画面が表示されました。

 ここで、sampledbにあるusersテーブルのレコードを新規追加したり、編集したり、削除したりといった簡単な作業ができることを確認しました。本当に簡単に動作させられたので、JRuby on Railsもいろいろと使えそうです。

$ export CLASSPATH=/usr/java/jdk/db/lib/derbyclient.jar:$CLASSPATH
$ jruby script/generate scaffold user
exists  app/controllers/
 
(略)
 
identical  public/stylesheets/scaffold.css
scaffold生成

JRubyとJavaを使って「Hello JRuby」

 ここまでで、JRubyでRailsを動かせることが分かりましたが、やはり、JRubyからJavaのクラスを呼び出す方法も確認しておきたいところです。

 JRubyにはサンプルが同梱されていたので、動作させてみました。見てみると、new演算は「java.io.FileReader.new filename」のように「クラス名.new」と記述して呼び出せますし、メソッドの呼び出しは、「br.readLine」のようにすれば良いようです。Javaのクラスが簡単に利用できるので、JavaプログラマだとRubyのクラスを使わずに、ついついJavaのクラスばかり使ってしまうかもしれません。

$ cd $JRUBY_HOME
$ jruby samples/java2.rb
------ ./samples/java2.rb------
require "java"
 
filename = "./samples/java2.rb"
fr = java.io.FileReader.new filename
br = java.io.BufferedReader.new fr
 
s = br.readLine
 
(略)
 
br.close
------ ./samples/java2.rb end ------
サンプルの実行例(JRuby 0.9.2に同梱されているサンプルより引用)

 次に、JavaからJRubyのクラスを呼び出す方法を調べてみました。java.netscriptingプロジェクトを見てみると、jruby-engine.jarを手に入れればいいようです。scriptingプロジェクトのメニューにドキュメントという項目があるので、ここからたどって、jsr223-engines.tar.gzをダウンロードしました。~/jsr223というディレクトリを作って、そこでこのファイルを展開すると、jruby/buildディレクトリの中にjruby-engine.jarがありました。後は、jruby.jarとjruby-engine.jarへクラスパスを通してプログラムをコンパイル実行すればいいだけです。次のようにして、RubyのスクリプトをJavaから呼び出せました。

public class RubyTest {

  public static void main(String[] args)

  throws javax.script.ScriptException {

    String program = "def hello(n)\n puts n\n end";

    javax.script.ScriptEngine ruby

      = new javax.script.ScriptEngineManager()

        .getEngineByName("jruby");

    ruby.eval(new java.io.StringReader(program));

    ruby.put("s", "Hello JRuby");

    ruby.eval("hello($s)");

  }

}

RubyTest.java
$ cd ~/jsr223/jruby/bin
$ javac -cp ../lib/jruby.jar:../build/jruby-engine.jar RubyTest.java
$ java -cp .:../lib/jruby.jar:../build/jruby-engine.jar RubyTest
Hello JRuby
実行例(~/jsr223/jruby/bin/RubyTest.java)

 念のため説明をしておくと、「def hello(n)\n puts n\n end」というRubyプログラムをString型の変数「program」へ入れて、ruby.eval()メソッドで実行できるようにしておきます。次に、ruby.put()メソッドで変数「s」へ「Hello JRuby」という文字列を設定しています。最後に、すでに使用可能になっているhelloというプログラムへ、「s」という引数を渡して実行することを、ruby.eval()メソッドにより行っているのです。

 変数の利用については、javax.script.ScriptContextを使って、変数スコープをコントロールしながら使う方法もあります。

public class RubyTest2 {

  public static void main(String[] args)

  throws javax.script.ScriptException {

    javax.script.ScriptEngine ruby

      = new javax.script.ScriptEngineManager()

        .getEngineByName("jruby");

    ruby.getContext().setAttribute("i", new Integer(1),

      javax.script.ScriptContext.ENGINE_SCOPE);

    ruby.eval("puts 2 + $i", ruby.getContext());

  }

}

RubyTest2.java

 参考までに、次の手順でコンソールからのスクリプト実行もできることが分かりました。jruby.shシェルスクリプトの中を見てみると、JDK 6に付属するツールのjrunscriptコマンドを使っていました。

$ cp ~/$JRUBY_HOME/lib/jruby.jar ~/jsr223/jruby/lib/
$ chmod 755 ~/jsr223/jruby/bin/jruby.sh; cd ~/jsr223/jruby/bin/
$ echo "puts 'Hello JRuby'" > Hello.rb
$ ./jruby.sh Hello.rb
Hello JRuby
スクリプト実行

 さて、Javaプログラマ流のRubyプログラミングということで、JRubyの使い方を紹介しました。JRubyについては、Appletで実行されるJRubyインタプリタが公開されていたり、Swingを使ったRubyの実行環境であるJRuby Consoleが開発されていたりと、何かと目が離せません。

 有名なMartin Fowler氏もJRubyを使ってVelocityを簡単に使う方法を考えたりしているようです。実は、Velocityはjava.netのscriptingプロジェクトで対象となっているので、直接使った方がいいのかもしれませんが、このあたりもまだまだ研究の余地が大いにあるということなのでしょう。いずれにせよ、しばらくはJavaとJRubyでいろいろと楽しめそうです。

編集部注:Velocityについての詳細を知りたい読者は、「Webアプリケーションフレームワークの定番」の「Velocity」をご参照願います。

筆者プロフィール

小山博史(こやま ひろし)

Webシステムの運用と開発、コンピュータと教育の研究に従事する傍ら、オープンソースソフトウェア、Java技術の普及のための活動を行っている。Ja-Jakartaプロジェクトへ参加し、コミッタの一員として活動を支えている。また、長野県の地域コミュニティである、SSS(G)bugs(J)の活動へも参加している。



Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。