Hand in hand is the only way to learn, always right way to learn.

Ruby Meets Internet Explorer 5 (maybe 4.x)


現在の実装状況 (2000/6/7更新)
以下は4/22から変わらず

さて、では実例をお見せしながら、解説しよう。サンプルのソースはここです。

6/22 注:IE内でのセキュリティチェックが実装されたため、以下のサンプルは動作しません。date.rbに対するrequireがエラーとなるため。単に、IE内でのRubyScriptの書き方のサンプルとなってしまいました。

これは、Ruby配布パッケージ内のbiorhythm.rb(Yasuo OHBAさん作成−著作権情報何も書いてないけどGPLだよね?違ったら、メイルお願いします。別のサンプルを元にします。)を元にしたHTMLです。
さて、スクリプトは以下の2つのScript要素としてHTMLに記述されています。

<script for=window event=onload language="RubyScript">
    @doc = @window.frm.document
</script>

これは、このHTMLがロード完了したときのイベント処理の記述です。
ここでモジュールの初期化処理を行なう必要があります。
実際には、すでにスクリプトをevalするために内部的にモジュールは生成されていますが。
ちなみにモジュールは無名で作成され、ActiveRubyScript内部でホスト単位に切り替えを行なっています。
このHTMLでは、バイオリズムグラフの出力をフローティングフレーム(frmという名前)に行なうため、該当ドキュメントをインスタンス変数に格納しています。また、ActiveScriptRubyの仕様により、トップレベルオブジェクトのwindowはモジュールのインスタンス変数として@windowで参照されます。
windowオブジェクトは、視覚要素を持たないため、HTML上に要素としてタグで表現されないので、イベントの記述は上の方法になりますが、それ以外のオブジェクトはすべてオブジェクトのタグ内に記述したほうが良いでしょう。

オキテ:インスタンス変数の初期化はwindowのonloadイベントまたはbodyのonloadに記述する。

さて、次のscript要素内には、
<script language="RubyScript">
include Math
require "date.rb"
def printHeader(doc, y, m, d, p, w)
  doc.write "--- Biorhythm ---<br>"
  doc.write sprintf("The birthday %04d.%02d.%02d is a %s<br>", y, m, d, w)
  doc.write sprintf("Age in days: [%d]<br><br>", p)
end

def getPosition(z)
  pi = 3.14159265
  phys = (50.0 * (1.0 + Math::sin((z / 23.0 - (z / 23)) * 360.0 * pi / 180.0))).to_i
  emot = (50.0 * (1.0 + Math::sin((z / 28.0 - (z / 28)) * 360.0 * pi / 180.0))).to_i
  geist =(50.0 * (1.0 + Math::sin((z / 33.0 - (z / 33)) * 360.0 * pi / 180.0))).to_i
  return phys, emot, geist
end

#
# main program
#
def main()
    begin
        bd = Date.new(@window.bday.value)
    rescue
        @window.alert "BAD Input Birthday !!"
        return nil
    end
    dd = Date.new(Time.now.strftime("%Y%m%d"))
    display_period = 9
    @doc.open "text/html", "replace"
    @doc.write "<center><span style=\"font-family: 'Courier'\">"
    printHeader(@doc, bd.year, bd.month, bd.day, dd.period - bd.period, bd.name_of_week)
    @doc.write "                     P=physical, E=emotional, M=mental<br>"
    @doc.write "             -------------------------+-------------------------<br>"
    @doc.write "                     Bad Condition    |    Good Condition<br>"
    @doc.write "             -------------------------+-------------------------<br>"
    for z in (dd.period - bd.period)..(dd.period - bd.period + display_period)
	phys, emot, geist = getPosition(z)
        @doc.write sprintf("%04d.%02d.%02d : <br>", dd.year, dd.month, dd.day)
        p = (phys / 2.0 + 0.5).to_i
        e = (emot / 2.0 + 0.5).to_i
        g = (geist / 2.0 + 0.5).to_i
        graph = "." * 51
        graph[25] = ?|
        graph[p], graph[e], graph[g] = ?P, ?E, ?M
        @doc.write graph + "<br>"
        dd = dd + 1
    end
    @doc.write "             -------------------------+-------------------------<br>"
    @doc.write "</span></center>"  
    @doc.close
end

def clear_input()
    @window.bday.value = ""
end
</script>

と、元のbiorhythm.rbが標準出力にプリントしていたものをフローティングフレーム内にHTMLとして出力するように変更しただけのものです。

オキテ:標準出力を使用するな。(食べたら死ぬで)標準出力が使用可能なのは、CScriptを使用したGlobalRubyScriptだけとなります。WScriptの場合はWSH経由の出力が必要です。またホストされる場合は、それぞれのホストオブジェクトの機構を使用してください。

ここで注意すべきは、例外の捕捉をきちんとすべきだということです。(入力から日付を作成している部分)
ただでさえ、わけのわからないハングアップや御臨終となるIEですので、障害の切り分けを行ないやすくするためにも、是非、例外の捕捉処理の記述は行なってください。

オキテ:例外捕捉をちゃんと記述しないとブラウザークラッシャーの出来上がり。
実際は、RScript内部で捕捉していますので、ブラウザークラッシャーにはなりませんが、例外が発生したというのが内部的にわかるだけで、利用者にフィードバックできないため、何が起きているのかわからないプログラムになってしまいます。
IEの左下にスクリプトエラー発生マークが出ることもありますので、その場合はクリックして内容を確認できます。ただし、行番号は常に1になります。また、IActiveScriptDebugインターフェイスは実装されていないため、スクリプトデバッガーを使用したデバッグは出来ません。

次に注意すべきことは、あくまでもイベントドリブン的な記述を行なう必要があるということです。すべて、メソッドの形式で記述してください。 そうでないと、思わぬタイミングで実行されることになり、確実にとらぶります。
ここでは、GOボタンのクリックでmainメソッドが呼ばれて処理を行なうようにしています。
最後の部分のclear_inputメソッドはclearボタンの処理です。フォームの形式でHTMLを作成していないため、resetタイプのボタンが使用できないからです。

オキテ:script要素内のすべての記述はメソッドとする。

すなわち
<script language="RubyScript">
 if ....

のようにscript要素に直接手続きを記述することは本質的に問題となります。こういった処理が必要な場合、既に書いたようにwindowまたはbodyのonloadイベントに記述してください。

で、次はHTML内の部品の記述方法ですが、下のように一般的な書式です。
<input type="button" value="GO!" id=start name=start onclick="main" language="RubyScript">
これで、このボタンをクリックすると、上のmainメソッドが呼び出されます。
さて、IE5(多分IE4でもOKかな?)とRScriptで試してください。

HTA

HTMLの拡張子をHTAに変更すると、そのまま実行可能なアプリケーションプログラムとなります。
ソケットを使用して指定されたHTMLのソースを表示するサンプルを作ってみました。表示にDHTMLを使用しているほかは、どうってことないものです。また、拡張子をHTMLに変更してもOKです。(IEのメニューや外枠が出るか出ないかだけの違いに過ぎないが、HTAのほうが起動が早い気がする)

ActiveXControlセキュリティのテスト

以下のようなHTMLを作成する
 <html>
  <head>
   <script language="rubyscript" for="window" event="onload">
     @window.alert "start test"
     x = WIN32OLE.new("Scripting.FileSystemObject")
     f = x.GetFile("c:\\autoexec.bat")
     @window.alert "autoexec.bat was created on " + f.DateCreated
   </script>
  </head>
  <body>
   What Am I Doing, hehe ?
  </body>
 </html>
"Scripting.FileSystemObject"は、安全では無いとマークされているため、 作成できない。これは例え、HTMLがローカルファイルとして存在しても。 ロードすると"start test"表示後、、IEの左角にエラーマークが出るので、 ダブルクリックすると、アクセス拒否例外があがったことが表示される。

セキュリティレベルのテスト

ついに、 テスト用スクリプトの一部を公開(6/7)
ボタンクリックで、2.C:\のファイル列挙、1.c:\にrubytestというディレクトリを作成しようとする。このバージョンからは、すべてエラーとなる。


GeoCities Japan

戻る
copyright(c) 2000 arton, Under GPL