JRuby Velocity

2007 年 1 月 19 日

昨天我需要使用 Velocity 來探索範本和巨集的一些東西。我喜歡 Velocity 的簡單範本語言,但這是其中一次我沒有在 Java 或 .NET 工作的背景下使用它。在這種情況下,使用 Velocity 會有點麻煩,因為你必須設定背景並在 Java 中執行處理器。

這種情況需要使用腳本語言,我偏好的腳本語言是 Ruby,因此我認為這是嘗試 JRuby 的好機會。我的結論是它運作得很好,但我會用細節來讓你感到無聊。

我下載了 JRuby 並將其解壓縮到 /usr/local/lib 中,並建立一個符號連結,以便我可以透過 /usr/local/lib/jruby 存取它。

然後我在 /usr/local/bin 中放置一個簡單的重新導向 shell。

JAVA_HOME=/usr/lib/jvm/java-1.5.0-sun
JRUBY_HOME=/usr/local/lib/jruby

/usr/local/lib/jruby/bin/jruby "$@"

然後我可以執行 JRuby。

$ jruby -v
ruby 1.8.5 (0) [java]

(實際上,我花了很長時間才讓它運作,我最後在椅子和鍵盤之間找到了錯誤。我太不好意思告訴你那是什麼了。)

若要執行 Velocity,你必須將它新增到 JRuby 的類別路徑中。

CLASSPATH=path/to/velocity-dep-1.4.jar
export CLASSPATH
jruby "$@"

為了協助執行 Velocity,我寫了一個小型的輔助類別。

require 'java'

class VelocityLauncher
  def initialize context, template
    @context = context
    @template = template
  end

  include_class 'org.apache.velocity.app.Velocity'
  include_class 'org.apache.velocity.VelocityContext'
  include_class 'java.io.StringWriter'

  def run
    vc = VelocityContext.new(@context)
    writer = StringWriter.new
    Velocity.init
    Velocity.evaluate(vc, writer, "LOG", @template)
    return writer.getBuffer
  end
end

現在我可以寫一個小範本

This is an announcement from $host

Our chief weapons are:
#foreach ($w in $weapons) 
  - $w 
#end

要填入資料,我只需要一個 Ruby hash,這很容易製作。

ct = {'host' => 'Cardinal Fang', 
  'weapons' => ['Fear', 'Surprise', 'Ruthless Efficiency']}
template = File.readlines('template.txt').join

puts VelocityLauncher.new(ct, template).run

我可以想像將它擴充為一個不錯的 Velocity 命令列執行器,它會採用以下格式的背景檔案

host = 'Cardinal Fang'
weapons = ['Fear', 'Surprise', 'Ruthless Efficiency']

但我現在不需要,所以我會在其他時間再做(而且我相當確定「其他時間」的約束是什麼)。