2007年6月22日 星期五

在 Java 中使用 JRuby & Gems

此篇文章鎖定的目標是,想在 Java 中,使用強大的 Ruby 語法,以及其他 Gems

換句話說,就是拿 Java 當飯吃,卻又想要偷吃 Ruby 的工程師們~囧



http://www.headius.com/jrubywiki/index.php/Java_Integration
JRuby wiki 中提到,要在 java 中使用 gems 需要注意兩件事。

1. jruby.base, jruby.home, jruby.lib, jruby.shell, and jruby.script. You can look in jruby.bat

wiki 中是這麼說,但是我並沒這麼做。我只做了底下這件事。

Ruby runtime = Ruby.getDefaultInstance();

runtime.setJRubyHome(JRUBY_HOME); // 需先設定好 JRUBY_HOME 環境變數

2. 這個就必須要乖乖照做,就是先觀察 jirb 底下 $: load path

["D:/JRuby/jruby-bin-1.0/jruby-1.0/lib/ruby/site_ruby/1.8",

"D:/JRuby/jruby-bin-1.0/jruby-1.0/lib/ruby/site_ruby",

"D:/JRuby/jruby-bin-1.0/jruby-1.0/lib/ruby/1.8",

"D:/JRuby/jruby-bin-1.0/jruby-1.0/lib/ruby/1.8/java",

"lib/ruby/1.8",

"."]

乖乖做吧

runtime.evalScript("$: << '" + JRUBY_HOME + "/lib/ruby/site_ruby/1.8'");

runtime.evalScript("$: << '" + JRUBY_HOME + "/lib/ruby/site_ruby'");

runtime.evalScript("$: << '" + JRUBY_HOME + "/lib/ruby/1.8'");

runtime.evalScript("$: << '" + JRUBY_HOME + "/lib/ruby/1.8/java'");

runtime.evalScript("$: << 'lib/ruby/1.8'");

以上狀況,皆為理想情況下,就能在 java 中使用 gems

但是,都沒提到,windows 需要注意的問題。


Windows 使用者,另外需要注意,目錄分隔符號。

問題出在底下程式碼 ( rubygems.rb )

# gem directories must come after -I and ENV['RUBYLIB']

$:.insert($:.index(sitelibdir), *require_paths)

稍微解釋一下

問題出在 $:.index(sitelibdir)

sitelibdir sitelibdir = Config::CONFIG['sitelibdir']

是從 require ‘rubygems’ require ‘rbconfig’ 定義好的

$jruby -rrbconfig -e "puts Config::CONFIG['sitelibdir']"
D:/JRuby/jruby-bin-1.0/jruby-1.0/lib/ruby/site_ruby/1.8


因為通常我們設定 windows 的環境變數,目錄分隔符號通常都是使用左上右下 => \

但是 rbconfig 所用的是 右上左下 => /

所以我們在定義 load path 之前,需要先把目錄分隔符號轉成 右上左下 => /


String JRUBY_HOME = System.getenv().get("JRUBY_HOME").replaceAll("\\\\", "/");


接下來安裝 台中邪惡 Ruby 最常用的 gem – hpricot

因為 ruby 許多東西為了增加效能或其他目的,某些部份可能會使用 C code

hpricot 也是如此,所以 hpricot 作者有改寫一個 JRuby 版本

參考 Ola Bini Hpricot goodness

$jruby bin/gem install hpricot --source http://code.whytheluckystiff.net

然後在 Java 中測試

runtime.evalScript("require 'rubygems'");

runtime.evalScript("require 'hpricot'");

runtime.evalScript("doc = Hpricot(open(\"http://redhanded.hobix.com/index.html\"))");

runtime.evalScript("puts doc");

或是跳過那難用的 Java Regexp

使用 Ruby Regexp

RubyString str = (RubyString) runtime.evalScript("$1 if 'a1b2c3' =~ /(\\d)/");

System.out.println(str.toString() + " = str");



以上程式碼,聰明的你應該想到該怎麼使用 Ruby 去載入 .rb 吧!

才不會像上面那麼難閱讀。


還有 過一陣子再來討論一下,為何不把 .rb 包成 jar 檔使用。

Can your Java do this?

呼應一下 Ola Bini blog Can your Ruby do this?

今天來介紹,用 ruby-uml 來畫 Java UML

首先使用 JRuby 安裝 ruby-uml

$jruby -S gem i ruby-uml





require 'rubygems'
require 'uml/class_diagram'

require 'java'
include_class 'java.util.Random'

filename = "Random.dot"
puts filename
cd = UML::ClassDiagram.new :show_private_methods => false,
:show_protected_methods => false,
:show_public_methods => true,
:cluster_packages => true,
:include => [/^Java/]

cd.include Java::JavaUtil::Random
Random.new(123)

File.open( filename, 'w' ) { |file|
file.write cd.to_dot
}

此處也呼應一下 thegiive JRuby 安裝方式

在上面程式碼當中,我們選擇使用 Class Diagram

:include => [/^Java/] # Java 開頭的我們才把他轉出

cd.include Java::JavaUtil::Random # Random 列入觀察物件

# 以下動作會繪製出相關的 Class Diagram

# 此處我們只把 Random 物件生成的相關 Class 列出來

Random.new(123)

執行完之後,會產生 Random.dot

dot 檔是一種描述階層或是有層次的指向圖形

又興趣的人可以用文字編輯器打開看看

接下來

請安裝 Graphviz

當中有個工具可以將 dot 檔轉換成圖形 (ex: png …)

在 程式集>>Graphviz>>dot


四個步驟就能把 dot 檔轉換成圖形

轉出結果如下



相關文章:(這不是打廣告 XD)

http://blog.xuite.net/jameschih/java/10184758

http://blog.xuite.net/jameschih/java/10185011